summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2011-05-11 20:53:37 +0100
committerKristian Monsen <kristianm@google.com>2011-05-16 13:54:48 +0100
commit21d179b334e59e9a3bfcaed4c4430bef1bc5759d (patch)
tree64e2bb6da27af6a5c93ca34f6051584aafbfcb9e /net
parent0c63f00edd6ed0482fd5cbcea937ca088baf7858 (diff)
downloadexternal_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.zip
external_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.tar.gz
external_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.tar.bz2
Merge Chromium at 10.0.621.0: Initial merge by git.
Change-Id: I070cc91c608dfa4a968a5a54c173260765ac8097
Diffstat (limited to 'net')
-rw-r--r--net/base/bandwidth_metrics.cc36
-rw-r--r--net/base/bandwidth_metrics.h26
-rw-r--r--net/base/capturing_net_log.cc28
-rw-r--r--net/base/capturing_net_log.h23
-rw-r--r--net/base/cert_database_nss_unittest.cc19
-rw-r--r--net/base/cert_database_openssl.cc20
-rw-r--r--net/base/cert_test_util.cc156
-rw-r--r--net/base/cert_test_util.h19
-rw-r--r--net/base/cert_verifier.cc505
-rw-r--r--net/base/cert_verifier.h184
-rw-r--r--net/base/cert_verifier_unittest.cc260
-rw-r--r--net/base/cookie_monster.cc31
-rw-r--r--net/base/cookie_monster.h46
-rw-r--r--net/base/cookie_monster_store_test.h16
-rw-r--r--net/base/cookie_monster_unittest.cc154
-rw-r--r--net/base/data_url.cc4
-rw-r--r--net/base/data_url.h3
-rw-r--r--net/base/data_url_unittest.cc14
-rw-r--r--net/base/directory_lister.cc7
-rw-r--r--net/base/directory_lister.h2
-rw-r--r--net/base/dnsrr_resolver.cc49
-rw-r--r--net/base/dnsrr_resolver.h11
-rw-r--r--net/base/escape.cc16
-rw-r--r--net/base/escape_unittest.cc54
-rw-r--r--net/base/forwarding_net_log.cc96
-rw-r--r--net/base/forwarding_net_log.h54
-rw-r--r--net/base/forwarding_net_log_unittest.cc84
-rw-r--r--net/base/host_resolver.cc8
-rw-r--r--net/base/host_resolver.h6
-rw-r--r--net/base/host_resolver_impl.cc4
-rw-r--r--net/base/host_resolver_impl.h2
-rw-r--r--net/base/host_resolver_impl_unittest.cc55
-rw-r--r--net/base/keygen_handler_openssl.cc32
-rw-r--r--net/base/keygen_handler_unittest.cc13
-rw-r--r--net/base/listen_socket.h4
-rw-r--r--net/base/load_flags_list.h2
-rw-r--r--net/base/load_states.h4
-rw-r--r--net/base/mime_sniffer.cc22
-rw-r--r--net/base/mime_util.cc39
-rw-r--r--net/base/net_error_list.h5
-rw-r--r--net/base/net_log.cc23
-rw-r--r--net/base/net_log.h31
-rw-r--r--net/base/net_log_event_type_list.h18
-rw-r--r--net/base/net_log_unittest.cc34
-rw-r--r--net/base/net_util.cc38
-rw-r--r--net/base/net_util.h15
-rw-r--r--net/base/openssl_memory_private_key_store.cc68
-rw-r--r--net/base/openssl_private_key_store.h51
-rw-r--r--net/base/registry_controlled_domain.h10
-rw-r--r--net/base/ssl_cert_request_info.cc5
-rw-r--r--net/base/ssl_cert_request_info.h3
-rw-r--r--net/base/ssl_cipher_suite_names.cc2
-rw-r--r--net/base/ssl_config_service.cc8
-rw-r--r--net/base/ssl_config_service.h25
-rw-r--r--net/base/ssl_config_service_mac.cc14
-rw-r--r--net/base/ssl_config_service_mac.h1
-rw-r--r--net/base/ssl_config_service_mac_unittest.cc26
-rw-r--r--net/base/ssl_config_service_win.cc9
-rw-r--r--net/base/ssl_config_service_win.h1
-rw-r--r--net/base/ssl_config_service_win_unittest.cc24
-rw-r--r--net/base/ssl_false_start_blacklist.txt20
-rw-r--r--net/base/test_root_certs.cc59
-rw-r--r--net/base/test_root_certs.h103
-rw-r--r--net/base/test_root_certs_mac.cc135
-rw-r--r--net/base/test_root_certs_nss.cc119
-rw-r--r--net/base/test_root_certs_openssl.cc51
-rw-r--r--net/base/test_root_certs_win.cc206
-rw-r--r--net/base/transport_security_state.cc36
-rw-r--r--net/base/transport_security_state.h3
-rw-r--r--net/base/transport_security_state_unittest.cc24
-rw-r--r--net/base/winsock_init.cc7
-rw-r--r--net/base/x509_cert_types.cc48
-rw-r--r--net/base/x509_cert_types.h22
-rw-r--r--net/base/x509_certificate.h41
-rw-r--r--net/base/x509_certificate_mac.cc207
-rw-r--r--net/base/x509_certificate_nss.cc114
-rw-r--r--net/base/x509_certificate_openssl.cc69
-rw-r--r--net/base/x509_certificate_unittest.cc67
-rw-r--r--net/base/x509_certificate_win.cc120
-rw-r--r--net/base/x509_openssl_util.cc65
-rw-r--r--net/base/x509_openssl_util_unittest.cc3
-rw-r--r--net/data/ftp/dir-listing-hprc-12
-rw-r--r--net/data/ftp/dir-listing-hprc-1.expected17
-rw-r--r--net/data/ftp/dir-listing-hprc-24
-rw-r--r--net/data/ftp/dir-listing-hprc-2.expected35
-rw-r--r--net/data/ftp/dir-listing-hprc-33
-rw-r--r--net/data/ftp/dir-listing-hprc-3.expected26
-rw-r--r--net/data/ftp/dir-listing-mlsd-15
-rw-r--r--net/data/ftp/dir-listing-mlsd-1.expected44
-rw-r--r--net/data/ftp/dir-listing-mlsd-21
-rw-r--r--net/data/ftp/dir-listing-mlsd-2.expected8
-rw-r--r--net/data/ssl/certificates/README5
-rw-r--r--net/data/ssl/certificates/unittest.key.binbin0 -> 635 bytes
-rw-r--r--net/data/ssl/certificates/unittest.selfsigned.derbin0 -> 414 bytes
-rw-r--r--net/disk_cache/backend_impl.cc13
-rw-r--r--net/disk_cache/backend_unittest.cc4
-rw-r--r--net/disk_cache/entry_impl.cc8
-rw-r--r--net/disk_cache/entry_unittest.cc49
-rw-r--r--net/disk_cache/file_win.cc11
-rw-r--r--net/disk_cache/in_flight_backend_io.cc27
-rw-r--r--net/disk_cache/in_flight_backend_io.h3
-rw-r--r--net/ftp/ftp_directory_listing_buffer.cc4
-rw-r--r--net/ftp/ftp_directory_listing_buffer_unittest.cc5
-rw-r--r--net/ftp/ftp_directory_listing_parser_hprc.cc60
-rw-r--r--net/ftp/ftp_directory_listing_parser_hprc.h46
-rw-r--r--net/ftp/ftp_directory_listing_parser_hprc_unittest.cc46
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls.cc4
-rw-r--r--net/ftp/ftp_directory_listing_parser_ls.h2
-rw-r--r--net/ftp/ftp_directory_listing_parser_mlsd.cc142
-rw-r--r--net/ftp/ftp_directory_listing_parser_mlsd.h37
-rw-r--r--net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc68
-rw-r--r--net/ftp/ftp_directory_listing_parser_netware.cc4
-rw-r--r--net/ftp/ftp_directory_listing_parser_netware.h2
-rw-r--r--net/ftp/ftp_directory_listing_parser_vms.cc4
-rw-r--r--net/ftp/ftp_directory_listing_parser_vms.h2
-rw-r--r--net/ftp/ftp_directory_listing_parser_windows.cc29
-rw-r--r--net/ftp/ftp_directory_listing_parser_windows.h2
-rw-r--r--net/ftp/ftp_directory_listing_parser_windows_unittest.cc27
-rw-r--r--net/ftp/ftp_network_transaction.cc47
-rw-r--r--net/ftp/ftp_network_transaction.h4
-rw-r--r--net/ftp/ftp_network_transaction_unittest.cc25
-rw-r--r--net/ftp/ftp_server_type_histograms.h4
-rw-r--r--net/http/des.cc10
-rw-r--r--net/http/disk_cache_based_ssl_host_info.cc41
-rw-r--r--net/http/disk_cache_based_ssl_host_info.h70
-rw-r--r--net/http/http_alternate_protocols.h1
-rw-r--r--net/http/http_auth_cache_unittest.cc2
-rw-r--r--net/http/http_auth_controller.cc87
-rw-r--r--net/http/http_auth_controller.h8
-rw-r--r--net/http/http_auth_gssapi_posix.cc5
-rw-r--r--net/http/http_auth_handler.cc12
-rw-r--r--net/http/http_auth_handler.h27
-rw-r--r--net/http/http_auth_handler_basic.cc1
-rw-r--r--net/http/http_auth_handler_basic.h2
-rw-r--r--net/http/http_auth_handler_digest.cc1
-rw-r--r--net/http/http_auth_handler_digest.h2
-rw-r--r--net/http/http_auth_handler_digest_unittest.cc157
-rw-r--r--net/http/http_auth_handler_mock.cc1
-rw-r--r--net/http/http_auth_handler_negotiate.cc1
-rw-r--r--net/http/http_auth_handler_ntlm.cc1
-rw-r--r--net/http/http_auth_handler_unittest.cc11
-rw-r--r--net/http/http_basic_stream.cc6
-rw-r--r--net/http/http_basic_stream.h8
-rw-r--r--net/http/http_cache.cc19
-rw-r--r--net/http/http_cache.h8
-rw-r--r--net/http/http_cache_transaction.cc29
-rw-r--r--net/http/http_cache_transaction.h3
-rw-r--r--net/http/http_cache_unittest.cc118
-rw-r--r--net/http/http_net_log_params.h4
-rw-r--r--net/http/http_network_layer.cc11
-rw-r--r--net/http/http_network_layer.h16
-rw-r--r--net/http/http_network_layer_unittest.cc7
-rw-r--r--net/http/http_network_session.cc3
-rw-r--r--net/http/http_network_session.h4
-rw-r--r--net/http/http_network_transaction.cc104
-rw-r--r--net/http/http_network_transaction.h7
-rw-r--r--net/http/http_network_transaction_unittest.cc590
-rw-r--r--net/http/http_proxy_client_socket.cc24
-rw-r--r--net/http/http_proxy_client_socket.h17
-rw-r--r--net/http/http_proxy_client_socket_pool.cc22
-rw-r--r--net/http/http_proxy_client_socket_pool.h15
-rw-r--r--net/http/http_proxy_client_socket_pool_unittest.cc19
-rw-r--r--net/http/http_response_body_drainer_unittest.cc1
-rw-r--r--net/http/http_stream_factory.h6
-rw-r--r--net/http/http_stream_factory_unittest.cc7
-rw-r--r--net/http/http_stream_request.cc101
-rw-r--r--net/http/http_stream_request.h15
-rw-r--r--net/http/proxy_client_socket.h35
-rw-r--r--net/http/stream_factory.h7
-rw-r--r--net/net.gyp91
-rw-r--r--net/ocsp/nss_ocsp.cc31
-rw-r--r--net/proxy/init_proxy_resolver_unittest.cc93
-rw-r--r--net/proxy/multi_threaded_proxy_resolver.cc22
-rw-r--r--net/proxy/multi_threaded_proxy_resolver_unittest.cc44
-rw-r--r--net/proxy/proxy_bypass_rules.cc63
-rw-r--r--net/proxy/proxy_bypass_rules.h23
-rw-r--r--net/proxy/proxy_config_service_fixed.cc20
-rw-r--r--net/proxy/proxy_config_service_fixed.h8
-rw-r--r--net/proxy/proxy_config_service_linux.cc12
-rw-r--r--net/proxy/proxy_config_service_linux.h15
-rw-r--r--net/proxy/proxy_resolver.h5
-rw-r--r--net/proxy/proxy_resolver_js_bindings_unittest.cc63
-rw-r--r--net/proxy/proxy_resolver_mac.cc21
-rw-r--r--net/proxy/proxy_resolver_mac.h14
-rw-r--r--net/proxy/proxy_resolver_v8.cc4
-rw-r--r--net/proxy/proxy_resolver_v8.h1
-rw-r--r--net/proxy/proxy_resolver_v8_unittest.cc4
-rw-r--r--net/proxy/proxy_resolver_winhttp.cc25
-rw-r--r--net/proxy/proxy_resolver_winhttp.h3
-rw-r--r--net/proxy/proxy_script_fetcher.h2
-rw-r--r--net/proxy/proxy_script_fetcher_impl.cc22
-rw-r--r--net/proxy/proxy_script_fetcher_impl.h23
-rw-r--r--net/proxy/proxy_script_fetcher_impl_unittest.cc9
-rw-r--r--net/proxy/proxy_service.cc29
-rw-r--r--net/proxy/proxy_service.h2
-rw-r--r--net/proxy/proxy_service_unittest.cc50
-rw-r--r--net/proxy/sync_host_resolver_bridge_unittest.cc4
-rw-r--r--net/server/http_listen_socket.cc10
-rw-r--r--net/server/http_listen_socket.h4
-rw-r--r--net/socket/client_socket_factory.cc25
-rw-r--r--net/socket/client_socket_factory.h6
-rw-r--r--net/socket/client_socket_pool.h4
-rw-r--r--net/socket/client_socket_pool_base.cc8
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc78
-rw-r--r--net/socket/client_socket_pool_manager.cc5
-rw-r--r--net/socket/client_socket_pool_manager.h11
-rw-r--r--net/socket/dns_cert_provenance_checker.cc44
-rw-r--r--net/socket/nss_ssl_util.cc240
-rw-r--r--net/socket/nss_ssl_util.h36
-rw-r--r--net/socket/socket_test_util.cc17
-rw-r--r--net/socket/socket_test_util.h8
-rw-r--r--net/socket/socks5_client_socket.cc4
-rw-r--r--net/socket/socks5_client_socket.h2
-rw-r--r--net/socket/socks5_client_socket_unittest.cc41
-rw-r--r--net/socket/socks_client_socket.cc4
-rw-r--r--net/socket/socks_client_socket.h2
-rw-r--r--net/socket/socks_client_socket_pool.cc12
-rw-r--r--net/socket/socks_client_socket_pool.h12
-rw-r--r--net/socket/socks_client_socket_unittest.cc59
-rw-r--r--net/socket/ssl_client_socket.cc62
-rw-r--r--net/socket/ssl_client_socket.h57
-rw-r--r--net/socket/ssl_client_socket_mac.cc41
-rw-r--r--net/socket/ssl_client_socket_mac.h7
-rw-r--r--net/socket/ssl_client_socket_mac_factory.cc4
-rw-r--r--net/socket/ssl_client_socket_mac_factory.h1
-rw-r--r--net/socket/ssl_client_socket_nss.cc282
-rw-r--r--net/socket/ssl_client_socket_nss.h9
-rw-r--r--net/socket/ssl_client_socket_nss_factory.cc3
-rw-r--r--net/socket/ssl_client_socket_nss_factory.h1
-rw-r--r--net/socket/ssl_client_socket_openssl.cc351
-rw-r--r--net/socket/ssl_client_socket_openssl.h31
-rw-r--r--net/socket/ssl_client_socket_pool.cc38
-rw-r--r--net/socket/ssl_client_socket_pool.h20
-rw-r--r--net/socket/ssl_client_socket_pool_unittest.cc7
-rw-r--r--net/socket/ssl_client_socket_snapstart_unittest.cc19
-rw-r--r--net/socket/ssl_client_socket_unittest.cc116
-rw-r--r--net/socket/ssl_client_socket_win.cc35
-rw-r--r--net/socket/ssl_client_socket_win.h7
-rw-r--r--net/socket/ssl_host_info.cc141
-rw-r--r--net/socket/ssl_host_info.h30
-rw-r--r--net/socket/ssl_host_info.proto34
-rw-r--r--net/socket/ssl_server_socket.h53
-rw-r--r--net/socket/ssl_server_socket_nss.cc677
-rw-r--r--net/socket/ssl_server_socket_nss.h133
-rw-r--r--net/socket/ssl_server_socket_unittest.cc369
-rw-r--r--net/socket/tcp_client_socket_libevent.cc4
-rw-r--r--net/socket/tcp_client_socket_libevent.h2
-rw-r--r--net/socket/tcp_client_socket_pool.cc31
-rw-r--r--net/socket/tcp_client_socket_pool.h26
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc3
-rw-r--r--net/socket/tcp_client_socket_unittest.cc10
-rw-r--r--net/socket_stream/socket_stream.cc6
-rw-r--r--net/socket_stream/socket_stream.h1
-rw-r--r--net/socket_stream/socket_stream_job.cc9
-rw-r--r--net/socket_stream/socket_stream_job_manager.cc7
-rw-r--r--net/socket_stream/socket_stream_job_manager.h9
-rw-r--r--net/socket_stream/socket_stream_metrics_unittest.cc2
-rw-r--r--net/spdy/spdy_http_stream.cc43
-rw-r--r--net/spdy/spdy_http_stream.h24
-rw-r--r--net/spdy/spdy_http_utils.h4
-rw-r--r--net/spdy/spdy_network_transaction_unittest.cc31
-rw-r--r--net/spdy/spdy_proxy_client_socket.cc25
-rw-r--r--net/spdy/spdy_proxy_client_socket.h19
-rw-r--r--net/spdy/spdy_proxy_client_socket_unittest.cc8
-rw-r--r--net/spdy/spdy_session.cc95
-rw-r--r--net/spdy/spdy_session.h4
-rw-r--r--net/spdy/spdy_stream.cc2
-rw-r--r--net/spdy/spdy_test_util.h9
-rw-r--r--net/test/test_server.cc40
-rw-r--r--net/test/test_server.h15
-rw-r--r--net/test/test_server_posix.cc6
-rw-r--r--net/test/test_server_win.cc28
-rw-r--r--net/tools/dump_cache/dump_cache.cc8
-rw-r--r--net/tools/fetch/fetch_client.cc19
-rw-r--r--net/tools/flip_server/balsa_headers.h19
-rw-r--r--net/tools/flip_server/flip_config.h64
-rw-r--r--net/tools/flip_server/flip_in_mem_edsm_server.cc226
-rwxr-xr-xnet/tools/testserver/testserver.py33
-rw-r--r--net/tools/testserver/xmppserver.py65
-rw-r--r--net/tools/testserver/xmppserver_test.py34
-rw-r--r--net/url_request/https_prober.cc22
-rw-r--r--net/url_request/https_prober.h35
-rw-r--r--net/url_request/url_request.cc33
-rw-r--r--net/url_request/url_request.h2
-rw-r--r--net/url_request/url_request_about_job.cc6
-rw-r--r--net/url_request/url_request_about_job.h6
-rw-r--r--net/url_request/url_request_context.cc5
-rw-r--r--net/url_request/url_request_context.h50
-rw-r--r--net/url_request/url_request_data_job.cc9
-rw-r--r--net/url_request/url_request_data_job.h8
-rw-r--r--net/url_request/url_request_error_job.cc6
-rw-r--r--net/url_request/url_request_error_job.h10
-rw-r--r--net/url_request/url_request_file_dir_job.cc27
-rw-r--r--net/url_request/url_request_file_dir_job.h6
-rw-r--r--net/url_request/url_request_file_job.cc54
-rw-r--r--net/url_request/url_request_file_job.h17
-rw-r--r--net/url_request/url_request_filter.cc31
-rw-r--r--net/url_request/url_request_filter.h17
-rw-r--r--net/url_request/url_request_ftp_job.cc83
-rw-r--r--net/url_request/url_request_ftp_job.h34
-rw-r--r--net/url_request/url_request_http_job.cc331
-rw-r--r--net/url_request/url_request_http_job.h56
-rw-r--r--net/url_request/url_request_job.cc6
-rw-r--r--net/url_request/url_request_job.h42
-rw-r--r--net/url_request/url_request_job_manager.cc53
-rw-r--r--net/url_request/url_request_job_manager.h48
-rw-r--r--net/url_request/url_request_job_metrics.cc8
-rw-r--r--net/url_request/url_request_job_metrics.h6
-rw-r--r--net/url_request/url_request_job_tracker.cc14
-rw-r--r--net/url_request/url_request_job_tracker.h34
-rw-r--r--net/url_request/url_request_job_tracker_unittest.cc39
-rw-r--r--net/url_request/url_request_netlog_params.cc6
-rw-r--r--net/url_request/url_request_netlog_params.h10
-rw-r--r--net/url_request/url_request_redirect_job.cc17
-rw-r--r--net/url_request/url_request_redirect_job.h10
-rw-r--r--net/url_request/url_request_simple_job.cc10
-rw-r--r--net/url_request/url_request_simple_job.h12
-rw-r--r--net/url_request/url_request_test_job.cc19
-rw-r--r--net/url_request/url_request_test_job.h8
-rw-r--r--net/url_request/url_request_throttler_entry.h4
-rw-r--r--net/url_request/url_request_throttler_entry_interface.h4
-rw-r--r--net/url_request/url_request_throttler_header_adapter.cc2
-rw-r--r--net/url_request/url_request_throttler_header_adapter.h2
-rw-r--r--net/url_request/url_request_throttler_manager.cc3
-rw-r--r--net/url_request/url_request_throttler_manager.h10
-rw-r--r--net/url_request/url_request_unittest.cc98
-rw-r--r--net/url_request/url_request_unittest.h27
-rw-r--r--net/websockets/websocket_job.cc22
-rw-r--r--net/websockets/websocket_job_unittest.cc4
-rw-r--r--net/websockets/websocket_net_log_params.cc51
-rw-r--r--net/websockets/websocket_net_log_params.h41
-rw-r--r--net/websockets/websocket_throttle.cc5
-rw-r--r--net/websockets/websocket_throttle.h6
333 files changed, 8434 insertions, 4342 deletions
diff --git a/net/base/bandwidth_metrics.cc b/net/base/bandwidth_metrics.cc
new file mode 100644
index 0000000..fa23a77
--- /dev/null
+++ b/net/base/bandwidth_metrics.cc
@@ -0,0 +1,36 @@
+// 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 "base/lazy_instance.h"
+#include "net/base/bandwidth_metrics.h"
+
+static base::LazyInstance<net::BandwidthMetrics> g_bandwidth_metrics(
+ base::LINKER_INITIALIZED);
+
+namespace net {
+
+ScopedBandwidthMetrics::ScopedBandwidthMetrics()
+ : started_(false) {
+}
+
+ScopedBandwidthMetrics::~ScopedBandwidthMetrics() {
+ if (started_)
+ g_bandwidth_metrics.Get().StopStream();
+}
+
+void ScopedBandwidthMetrics::StartStream() {
+ started_ = true;
+ g_bandwidth_metrics.Get().StartStream();
+}
+
+void ScopedBandwidthMetrics::StopStream() {
+ started_ = false;
+ g_bandwidth_metrics.Get().StopStream();
+}
+
+void ScopedBandwidthMetrics::RecordBytes(int bytes) {
+ g_bandwidth_metrics.Get().RecordBytes(bytes);
+}
+
+} // namespace net
diff --git a/net/base/bandwidth_metrics.h b/net/base/bandwidth_metrics.h
index 80fa005..ce1a498 100644
--- a/net/base/bandwidth_metrics.h
+++ b/net/base/bandwidth_metrics.h
@@ -121,33 +121,17 @@ class BandwidthMetrics {
// ensure we always stop them.
class ScopedBandwidthMetrics {
public:
- explicit ScopedBandwidthMetrics(BandwidthMetrics* metrics)
- : metrics_(metrics), started_(false) {
- }
-
- ~ScopedBandwidthMetrics() {
- if (started_)
- metrics_->StopStream();
- }
-
- void StartStream() {
- started_ = true;
- metrics_->StartStream();
- }
+ ScopedBandwidthMetrics();
+ ~ScopedBandwidthMetrics();
- void StopStream() {
- started_ = false;
- metrics_->StopStream();
- }
-
- void RecordBytes(int bytes) { metrics_->RecordBytes(bytes); }
+ void StartStream();
+ void StopStream();
+ void RecordBytes(int bytes);
private:
- BandwidthMetrics* metrics_;
bool started_;
};
} // namespace net
#endif // NET_BASE_BANDWIDTH_METRICS_H_
-
diff --git a/net/base/capturing_net_log.cc b/net/base/capturing_net_log.cc
index c488e06..fccd5ae 100644
--- a/net/base/capturing_net_log.cc
+++ b/net/base/capturing_net_log.cc
@@ -18,7 +18,7 @@ CapturingNetLog::Entry::Entry(EventType type,
CapturingNetLog::Entry::~Entry() {}
CapturingNetLog::CapturingNetLog(size_t max_num_entries)
- : next_id_(0), max_num_entries_(max_num_entries) {
+ : last_id_(-1), max_num_entries_(max_num_entries) {
}
CapturingNetLog::~CapturingNetLog() {}
@@ -28,16 +28,27 @@ void CapturingNetLog::AddEntry(EventType type,
const Source& source,
EventPhase phase,
EventParameters* extra_parameters) {
+ AutoLock lock(lock_);
Entry entry(type, time, source, phase, extra_parameters);
if (entries_.size() + 1 < max_num_entries_)
entries_.push_back(entry);
}
uint32 CapturingNetLog::NextID() {
- return next_id_++;
+ return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
+}
+
+NetLog::LogLevel CapturingNetLog::GetLogLevel() const {
+ return LOG_ALL_BUT_BYTES;
+}
+
+void CapturingNetLog::GetEntries(EntryList* entry_list) const {
+ AutoLock lock(lock_);
+ *entry_list = entries_;
}
void CapturingNetLog::Clear() {
+ AutoLock lock(lock_);
entries_.clear();
}
@@ -51,16 +62,13 @@ CapturingBoundNetLog::CapturingBoundNetLog(size_t max_num_entries)
CapturingBoundNetLog::~CapturingBoundNetLog() {}
-void CapturingBoundNetLog::Clear() {
- capturing_net_log_->Clear();
+void CapturingBoundNetLog::GetEntries(
+ CapturingNetLog::EntryList* entry_list) const {
+ capturing_net_log_->GetEntries(entry_list);
}
-void CapturingBoundNetLog::AppendTo(const BoundNetLog& net_log) const {
- for (size_t i = 0; i < entries().size(); ++i) {
- const CapturingNetLog::Entry& entry = entries()[i];
- net_log.AddEntryWithTime(entry.type, entry.time, entry.phase,
- entry.extra_parameters);
- }
+void CapturingBoundNetLog::Clear() {
+ capturing_net_log_->Clear();
}
} // namespace net
diff --git a/net/base/capturing_net_log.h b/net/base/capturing_net_log.h
index ff7cf16..9254725 100644
--- a/net/base/capturing_net_log.h
+++ b/net/base/capturing_net_log.h
@@ -8,7 +8,9 @@
#include <vector>
+#include "base/atomicops.h"
#include "base/basictypes.h"
+#include "base/lock.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
@@ -52,15 +54,20 @@ class CapturingNetLog : public NetLog {
EventPhase phase,
EventParameters* extra_parameters);
virtual uint32 NextID();
- virtual LogLevel GetLogLevel() const { return LOG_ALL_BUT_BYTES; }
+ virtual LogLevel GetLogLevel() const;
// Returns the list of all entries in the log.
- const EntryList& entries() const { return entries_; }
+ void GetEntries(EntryList* entry_list) const;
void Clear();
private:
- uint32 next_id_;
+ // Needs to be "mutable" so can use it in GetEntries().
+ mutable Lock lock_;
+
+ // Last assigned source ID. Incremented to get the next one.
+ base::subtle::Atomic32 last_id_;
+
size_t max_num_entries_;
EntryList entries_;
@@ -85,17 +92,11 @@ class CapturingBoundNetLog {
return BoundNetLog(source_, capturing_net_log_.get());
}
- // Returns the list of all entries in the log.
- const CapturingNetLog::EntryList& entries() const {
- return capturing_net_log_->entries();
- }
+ // Fills |entry_list| with all entries in the log.
+ void GetEntries(CapturingNetLog::EntryList* entry_list) const;
void Clear();
- // Sends all of captured messages to |net_log|, using the same source ID
- // as |net_log|.
- void AppendTo(const BoundNetLog& net_log) const;
-
private:
NetLog::Source source_;
scoped_ptr<CapturingNetLog> capturing_net_log_;
diff --git a/net/base/cert_database_nss_unittest.cc b/net/base/cert_database_nss_unittest.cc
index 5056e5d..8e69104 100644
--- a/net/base/cert_database_nss_unittest.cc
+++ b/net/base/cert_database_nss_unittest.cc
@@ -104,16 +104,9 @@ bool ReadCertIntoList(const std::string& name, CertificateList* certs) {
class CertDatabaseNSSTest : public testing::Test {
public:
virtual void SetUp() {
- if (!temp_db_initialized_) {
- ScopedTempDir* temp_db_dir = Singleton<
- ScopedTempDir,
- DefaultSingletonTraits<ScopedTempDir>,
- CertDatabaseNSSTest>::get();
- ASSERT_TRUE(temp_db_dir->CreateUniqueTempDir());
- ASSERT_TRUE(
- base::OpenTestNSSDB(temp_db_dir->path(), "CertDatabaseNSSTest db"));
- temp_db_initialized_ = true;
- }
+ ASSERT_TRUE(temp_db_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::OpenTestNSSDB(temp_db_dir_.path(), "CertDatabaseNSSTest db"));
slot_.reset(base::GetDefaultNSSKeySlot());
// Test db should be empty at start of test.
@@ -121,7 +114,6 @@ class CertDatabaseNSSTest : public testing::Test {
}
virtual void TearDown() {
// Don't try to cleanup if the setup failed.
- ASSERT_TRUE(temp_db_initialized_);
ASSERT_TRUE(slot_.get());
EXPECT_TRUE(CleanupSlotContents(slot_.get()));
@@ -133,12 +125,9 @@ class CertDatabaseNSSTest : public testing::Test {
CertDatabase cert_db_;
private:
- static bool temp_db_initialized_;
+ ScopedTempDir temp_db_dir_;
};
-// static
-bool CertDatabaseNSSTest::temp_db_initialized_ = false;
-
TEST_F(CertDatabaseNSSTest, ListCerts) {
// This test isn't terribly useful, though it will at least let valgrind test
// for leaks.
diff --git a/net/base/cert_database_openssl.cc b/net/base/cert_database_openssl.cc
index 73a67c1..ec5ec24 100644
--- a/net/base/cert_database_openssl.cc
+++ b/net/base/cert_database_openssl.cc
@@ -4,7 +4,11 @@
#include "net/base/cert_database.h"
+#include <openssl/x509.h>
+
+#include "base/logging.h"
#include "net/base/net_errors.h"
+#include "net/base/openssl_private_key_store.h"
#include "net/base/x509_certificate.h"
namespace net {
@@ -18,22 +22,28 @@ int CertDatabase::CheckUserCert(X509Certificate* cert) {
if (cert->HasExpired())
return ERR_CERT_DATE_INVALID;
- // TODO(bulach): implement me.
- return ERR_NOT_IMPLEMENTED;
+ if (!OpenSSLPrivateKeyStore::GetInstance()->FetchPrivateKey(
+ X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle()))))
+ return ERR_NO_PRIVATE_KEY_FOR_CERT;
+
+ return OK;
}
int CertDatabase::AddUserCert(X509Certificate* cert) {
// TODO(bulach): implement me.
+ NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}
void CertDatabase::ListCerts(CertificateList* certs) {
// TODO(bulach): implement me.
+ NOTIMPLEMENTED();
}
int CertDatabase::ImportFromPKCS12(const std::string& data,
const string16& password) {
// TODO(bulach): implement me.
+ NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}
@@ -41,18 +51,20 @@ int CertDatabase::ExportToPKCS12(const CertificateList& certs,
const string16& password,
std::string* output) const {
// TODO(bulach): implement me.
+ NOTIMPLEMENTED();
return 0;
}
bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) {
// TODO(bulach): implement me.
+ NOTIMPLEMENTED();
return false;
}
unsigned int CertDatabase::GetCertTrust(const X509Certificate* cert,
CertType type) const {
// TODO(bulach): implement me.
- // NOTE: This method is currently only declared for USE_NSS builds.
+ NOTIMPLEMENTED();
return 0;
}
@@ -60,7 +72,7 @@ bool CertDatabase::SetCertTrust(const X509Certificate* cert,
CertType type,
unsigned int trust_bits) {
// TODO(bulach): implement me.
- // NOTE: This method is currently only declared for USE_NSS builds.
+ NOTIMPLEMENTED();
return false;
}
diff --git a/net/base/cert_test_util.cc b/net/base/cert_test_util.cc
index df00b9d..fb0c0f8 100644
--- a/net/base/cert_test_util.cc
+++ b/net/base/cert_test_util.cc
@@ -4,153 +4,37 @@
#include "net/base/cert_test_util.h"
-#include "build/build_config.h"
-
-#if defined(USE_OPENSSL)
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-#include <openssl/x509v3.h>
-#include "base/openssl_util.h"
-#elif defined(USE_NSS)
-#include <cert.h>
-#include "base/nss_util.h"
-#elif defined(OS_MACOSX)
-#include <Security/Security.h>
-#include "base/mac/scoped_cftyperef.h"
-#endif
-
+#include "base/file_path.h"
#include "base/file_util.h"
-#include "base/logging.h"
#include "base/path_service.h"
#include "net/base/x509_certificate.h"
namespace net {
-#if defined(USE_OPENSSL)
-X509Certificate* AddTemporaryRootCertToStore(X509* x509_cert) {
- if (!X509_STORE_add_cert(X509Certificate::cert_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) {
- base::ClearOpenSSLERRStack(FROM_HERE);
- return NULL;
- }
- }
- return X509Certificate::CreateFromHandle(
- x509_cert, X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
-}
-
-X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
- base::EnsureOpenSSLInit();
-
- std::string rawcert;
- if (!file_util::ReadFileToString(filename, &rawcert)) {
- LOG(ERROR) << "Can't load certificate " << filename.value();
- return NULL;
- }
-
- base::ScopedOpenSSL<BIO, BIO_free_all> cert_bio(
- BIO_new_mem_buf(const_cast<char*>(rawcert.c_str()),
- rawcert.length()));
- if (!cert_bio.get()) {
- LOG(ERROR) << "Can't create read-only BIO " << filename.value();
- return NULL;
- }
-
- base::ScopedOpenSSL<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();
- base::ScopedOpenSSL<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;
+FilePath GetTestCertsDirectory() {
+ FilePath certs_dir;
+ PathService::Get(base::DIR_SOURCE_ROOT, &certs_dir);
+ certs_dir = certs_dir.AppendASCII("net");
+ certs_dir = certs_dir.AppendASCII("data");
+ certs_dir = certs_dir.AppendASCII("ssl");
+ certs_dir = certs_dir.AppendASCII("certificates");
+ return certs_dir;
}
-#elif defined(USE_NSS)
-X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
- base::EnsureNSSInit();
- std::string rawcert;
- if (!file_util::ReadFileToString(filename, &rawcert)) {
- LOG(ERROR) << "Can't load certificate " << filename.value();
+scoped_refptr<X509Certificate> ImportCertFromFile(
+ const FilePath& certs_dir,
+ const std::string& cert_file) {
+ FilePath cert_path = certs_dir.AppendASCII(cert_file);
+ std::string cert_data;
+ if (!file_util::ReadFileToString(cert_path, &cert_data))
return NULL;
- }
- CERTCertificate *cert;
- cert = CERT_DecodeCertFromPackage(const_cast<char *>(rawcert.c_str()),
- rawcert.length());
- if (!cert) {
- LOG(ERROR) << "Can't convert certificate " << filename.value();
+ CertificateList certs_in_file =
+ X509Certificate::CreateCertificateListFromBytes(
+ cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
+ if (certs_in_file.empty())
return NULL;
- }
-
- // TODO(port): remove this const_cast after NSS 3.12.3 is released
- CERTCertTrust trust;
- int rv = CERT_DecodeTrustString(&trust, const_cast<char *>("TCu,Cu,Tu"));
- if (rv != SECSuccess) {
- LOG(ERROR) << "Can't decode trust string";
- CERT_DestroyCertificate(cert);
- return NULL;
- }
-
- rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust);
- if (rv != SECSuccess) {
- LOG(ERROR) << "Can't change trust for certificate " << filename.value();
- CERT_DestroyCertificate(cert);
- return NULL;
- }
-
- X509Certificate* result = X509Certificate::CreateFromHandle(
- cert,
- X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
- CERT_DestroyCertificate(cert);
- return result;
-}
-#endif
-
-#if defined(OS_MACOSX)
-X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
- std::string rawcert;
- if (!file_util::ReadFileToString(filename, &rawcert)) {
- LOG(ERROR) << "Can't load certificate " << filename.value();
- return NULL;
- }
-
- CFDataRef pem = CFDataCreate(kCFAllocatorDefault,
- reinterpret_cast<const UInt8*>(rawcert.data()),
- static_cast<CFIndex>(rawcert.size()));
- if (!pem)
- return NULL;
- base::mac::ScopedCFTypeRef<CFDataRef> scoped_pem(pem);
-
- SecExternalFormat input_format = kSecFormatUnknown;
- SecExternalItemType item_type = kSecItemTypeUnknown;
- CFArrayRef cert_array = NULL;
- if (SecKeychainItemImport(pem, NULL, &input_format, &item_type, 0, NULL, NULL,
- &cert_array))
- return NULL;
- base::mac::ScopedCFTypeRef<CFArrayRef> scoped_cert_array(cert_array);
-
- if (!CFArrayGetCount(cert_array))
- return NULL;
-
- SecCertificateRef cert_ref = static_cast<SecCertificateRef>(
- const_cast<void*>(CFArrayGetValueAtIndex(cert_array, 0)));
-
- return X509Certificate::CreateFromHandle(cert_ref,
- X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
+ return certs_in_file[0];
}
-#endif
} // namespace net
diff --git a/net/base/cert_test_util.h b/net/base/cert_test_util.h
index 8709156..3452ac5 100644
--- a/net/base/cert_test_util.h
+++ b/net/base/cert_test_util.h
@@ -6,7 +6,9 @@
#define NET_BASE_CERT_TEST_UTIL_H_
#pragma once
-#include "build/build_config.h"
+#include <string>
+
+#include "base/ref_counted.h"
class FilePath;
@@ -14,11 +16,16 @@ namespace net {
class X509Certificate;
-#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);
-#endif
+// Returns a FilePath object representing the src/net/data/ssl/certificates
+// directory in the source tree.
+FilePath GetTestCertsDirectory();
+
+// Imports a certificate file in the src/net/data/ssl/certificates directory.
+// certs_dir represents the test certificates directory. cert_file is the
+// name of the certificate file. If cert_file contains multiple certificates,
+// the first certificate found will be returned.
+scoped_refptr<X509Certificate> ImportCertFromFile(const FilePath& certs_dir,
+ const std::string& cert_file);
} // namespace net
diff --git a/net/base/cert_verifier.cc b/net/base/cert_verifier.cc
index ae910b4..4b3d904 100644
--- a/net/base/cert_verifier.cc
+++ b/net/base/cert_verifier.cc
@@ -1,45 +1,158 @@
-// Copyright (c) 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.
#include "net/base/cert_verifier.h"
-#if defined(USE_NSS)
-#include <private/pprthred.h> // PR_DetatchThread
-#endif
-
+#include "base/compiler_specific.h"
#include "base/lock.h"
-#include "base/message_loop_proxy.h"
-#include "base/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/stl_util-inl.h"
#include "base/worker_pool.h"
-#include "net/base/cert_verify_result.h"
#include "net/base/net_errors.h"
#include "net/base/x509_certificate.h"
+#if defined(USE_NSS)
+#include <private/pprthred.h> // PR_DetachThread
+#endif
+
namespace net {
-class CertVerifier::Request :
- public base::RefCountedThreadSafe<CertVerifier::Request> {
+////////////////////////////////////////////////////////////////////////////
+
+// Life of a request:
+//
+// CertVerifier CertVerifierJob CertVerifierWorker Request
+// | (origin loop) (worker loop)
+// |
+// Verify()
+// |---->-------------------<creates>
+// |
+// |---->----<creates>
+// |
+// |---->---------------------------------------------------<creates>
+// |
+// |---->--------------------Start
+// | |
+// | PostTask
+// |
+// | <starts verifying>
+// |---->-----AddRequest |
+// |
+// |
+// |
+// Finish
+// |
+// PostTask
+//
+// |
+// DoReply
+// |----<-----------------------|
+// HandleResult
+// |
+// |---->-----HandleResult
+// |
+// |------>-----------------------------------Post
+//
+//
+//
+// On a cache hit, CertVerifier::Verify() returns synchronously without
+// posting a task to a worker thread.
+
+// The number of CachedCertVerifyResult objects that we'll cache.
+static const unsigned kMaxCacheEntries = 256;
+
+// The number of seconds for which we'll cache a cache entry.
+static const unsigned kTTLSecs = 1800; // 30 minutes.
+
+namespace {
+
+class DefaultTimeService : public CertVerifier::TimeService {
+ public:
+ // CertVerifier::TimeService methods:
+ virtual base::Time Now() { return base::Time::Now(); }
+};
+
+} // namespace
+
+CachedCertVerifyResult::CachedCertVerifyResult() : error(ERR_FAILED) {
+}
+
+CachedCertVerifyResult::~CachedCertVerifyResult() {}
+
+bool CachedCertVerifyResult::HasExpired(const base::Time current_time) const {
+ return current_time >= expiry;
+}
+
+// Represents the output and result callback of a request.
+class CertVerifierRequest {
public:
- Request(CertVerifier* verifier,
- X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CertVerifyResult* verify_result,
- CompletionCallback* callback)
+ CertVerifierRequest(CompletionCallback* callback,
+ CertVerifyResult* verify_result)
+ : callback_(callback),
+ verify_result_(verify_result) {
+ }
+
+ // Ensures that the result callback will never be made.
+ void Cancel() {
+ callback_ = NULL;
+ verify_result_ = NULL;
+ }
+
+ // Copies the contents of |verify_result| to the caller's
+ // CertVerifyResult and calls the callback.
+ void Post(const CachedCertVerifyResult& verify_result) {
+ if (callback_) {
+ *verify_result_ = verify_result.result;
+ callback_->Run(verify_result.error);
+ }
+ delete this;
+ }
+
+ private:
+ CompletionCallback* callback_;
+ CertVerifyResult* verify_result_;
+};
+
+
+// CertVerifierWorker runs on a worker thread and takes care of the blocking
+// process of performing the certificate verification. Deletes itself
+// eventually if Start() succeeds.
+class CertVerifierWorker {
+ public:
+ CertVerifierWorker(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CertVerifier* cert_verifier)
: cert_(cert),
hostname_(hostname),
flags_(flags),
- verifier_(verifier),
- verify_result_(verify_result),
- callback_(callback),
- origin_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()),
- error_(OK) {
+ origin_loop_(MessageLoop::current()),
+ cert_verifier_(cert_verifier),
+ canceled_(false),
+ error_(ERR_FAILED) {
+ }
+
+ bool Start() {
+ DCHECK_EQ(MessageLoop::current(), origin_loop_);
+
+ return WorkerPool::PostTask(
+ FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run),
+ true /* task is slow */);
}
- void DoVerify() {
- // Running on the worker thread
- error_ = cert_->Verify(hostname_, flags_, &result_);
+ // Cancel is called from the origin loop when the CertVerifier is getting
+ // deleted.
+ void Cancel() {
+ DCHECK_EQ(MessageLoop::current(), origin_loop_);
+ AutoLock locked(lock_);
+ canceled_ = true;
+ }
+
+ private:
+ void Run() {
+ // Runs on a worker thread.
+ error_ = cert_->Verify(hostname_, flags_, &verify_result_);
#if defined(USE_NSS)
// Detach the thread from NSPR.
// Calling NSS functions attaches the thread to NSPR, which stores
@@ -50,109 +163,319 @@ class CertVerifier::Request :
// destructors run.
PR_DetachThread();
#endif
+ Finish();
+ }
- scoped_ptr<Task> reply(NewRunnableMethod(this, &Request::DoCallback));
-
- // The origin loop could go away while we are trying to post to it, so we
- // need to call its PostTask method inside a lock. See ~CertVerifier.
- AutoLock locked(origin_loop_proxy_lock_);
- if (origin_loop_proxy_) {
- bool posted = origin_loop_proxy_->PostTask(FROM_HERE, reply.release());
- // TODO(willchan): Fix leaks and then change this to a DCHECK.
- LOG_IF(ERROR, !posted) << "Leaked CertVerifier!";
+ // DoReply runs on the origin thread.
+ void DoReply() {
+ DCHECK_EQ(MessageLoop::current(), origin_loop_);
+ {
+ // We lock here because the worker thread could still be in Finished,
+ // after the PostTask, but before unlocking |lock_|. If we do not lock in
+ // this case, we will end up deleting a locked Lock, which can lead to
+ // memory leaks or worse errors.
+ AutoLock locked(lock_);
+ if (!canceled_) {
+ cert_verifier_->HandleResult(cert_, hostname_, flags_,
+ error_, verify_result_);
+ }
}
+ delete this;
}
- void DoCallback() {
- // Running on the origin thread.
+ void Finish() {
+ // Runs on the worker thread.
+ // We assume that the origin loop outlives the CertVerifier. If the
+ // CertVerifier is deleted, it will call Cancel on us. If it does so
+ // before the Acquire, we'll delete ourselves and return. If it's trying to
+ // do so concurrently, then it'll block on the lock and we'll call PostTask
+ // while the CertVerifier (and therefore the MessageLoop) is still alive.
+ // If it does so after this function, we assume that the MessageLoop will
+ // process pending tasks. In which case we'll notice the |canceled_| flag
+ // in DoReply.
- // We may have been cancelled!
- if (!verifier_)
- return;
+ bool canceled;
+ {
+ AutoLock locked(lock_);
+ canceled = canceled_;
+ if (!canceled) {
+ origin_loop_->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply));
+ }
+ }
- *verify_result_ = result_;
+ if (canceled)
+ delete this;
+ }
- // Drop the verifier's reference to us. Do this before running the
- // callback since the callback might result in the verifier being
- // destroyed.
- verifier_->request_ = NULL;
+ scoped_refptr<X509Certificate> cert_;
+ const std::string hostname_;
+ const int flags_;
+ MessageLoop* const origin_loop_;
+ CertVerifier* const cert_verifier_;
- callback_->Run(error_);
- }
+ // lock_ protects canceled_.
+ Lock lock_;
- void Cancel() {
- verifier_ = NULL;
+ // If canceled_ is true,
+ // * origin_loop_ cannot be accessed by the worker thread,
+ // * cert_verifier_ cannot be accessed by any thread.
+ bool canceled_;
+
+ int error_;
+ CertVerifyResult verify_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker);
+};
- AutoLock locked(origin_loop_proxy_lock_);
- origin_loop_proxy_ = NULL;
+// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It
+// lives only on the CertVerifier's origin message loop.
+class CertVerifierJob {
+ public:
+ explicit CertVerifierJob(CertVerifierWorker* worker) : worker_(worker) {
}
- private:
- friend class base::RefCountedThreadSafe<CertVerifier::Request>;
+ ~CertVerifierJob() {
+ if (worker_)
+ worker_->Cancel();
+ }
- ~Request() {}
+ void AddRequest(CertVerifierRequest* request) {
+ requests_.push_back(request);
+ }
- // Set on the origin thread, read on the worker thread.
- scoped_refptr<X509Certificate> cert_;
- std::string hostname_;
- // bitwise OR'd of X509Certificate::VerifyFlags.
- int flags_;
+ void HandleResult(const CachedCertVerifyResult& verify_result) {
+ worker_ = NULL;
+ PostAll(verify_result);
+ }
- // Only used on the origin thread (where Verify was called).
- CertVerifier* verifier_;
- CertVerifyResult* verify_result_;
- CompletionCallback* callback_;
+ private:
+ void PostAll(const CachedCertVerifyResult& verify_result) {
+ std::vector<CertVerifierRequest*> requests;
+ requests_.swap(requests);
- // Used to post ourselves onto the origin thread.
- Lock origin_loop_proxy_lock_;
- // Use a MessageLoopProxy in case the owner of the CertVerifier is leaked, so
- // this code won't crash: http://crbug.com/42275. If this is leaked, then it
- // doesn't get Cancel()'d, so |origin_loop_proxy_| doesn't get NULL'd out. If
- // the MessageLoop goes away, then if we had used a MessageLoop, this would
- // crash.
- scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_;
+ for (std::vector<CertVerifierRequest*>::iterator
+ i = requests.begin(); i != requests.end(); i++) {
+ (*i)->Post(verify_result);
+ // Post() causes the CertVerifierRequest to delete itself.
+ }
+ }
- // Assigned on the worker thread, read on the origin thread.
- int error_;
- CertVerifyResult result_;
+ std::vector<CertVerifierRequest*> requests_;
+ CertVerifierWorker* worker_;
};
-//-----------------------------------------------------------------------------
-CertVerifier::CertVerifier() {
+CertVerifier::CertVerifier()
+ : time_service_(new DefaultTimeService),
+ requests_(0),
+ cache_hits_(0),
+ inflight_joins_(0) {
+}
+
+CertVerifier::CertVerifier(TimeService* time_service)
+ : time_service_(time_service),
+ requests_(0),
+ cache_hits_(0),
+ inflight_joins_(0) {
}
CertVerifier::~CertVerifier() {
- if (request_)
- request_->Cancel();
+ STLDeleteValues(&inflight_);
}
int CertVerifier::Verify(X509Certificate* cert,
const std::string& hostname,
int flags,
CertVerifyResult* verify_result,
- CompletionCallback* callback) {
- DCHECK(!request_) << "verifier already in use";
+ CompletionCallback* callback,
+ RequestHandle* out_req) {
+ DCHECK(CalledOnValidThread());
- // Do a synchronous verification.
- if (!callback) {
- CertVerifyResult result;
- int rv = cert->Verify(hostname, flags, &result);
- *verify_result = result;
- return rv;
+ if (!callback || !verify_result || hostname.empty()) {
+ *out_req = NULL;
+ return ERR_INVALID_ARGUMENT;
}
- request_ = new Request(this, cert, hostname, flags, verify_result, callback);
+ requests_++;
- // Dispatch to worker thread...
- if (!WorkerPool::PostTask(FROM_HERE,
- NewRunnableMethod(request_.get(), &Request::DoVerify), true)) {
- NOTREACHED();
- request_ = NULL;
- return ERR_FAILED;
+ const RequestParams key = {cert->fingerprint(), hostname, flags};
+ // First check the cache.
+ std::map<RequestParams, CachedCertVerifyResult>::iterator i;
+ i = cache_.find(key);
+ if (i != cache_.end()) {
+ if (!i->second.HasExpired(time_service_->Now())) {
+ cache_hits_++;
+ *out_req = NULL;
+ *verify_result = i->second.result;
+ return i->second.error;
+ }
+ // Cache entry has expired.
+ cache_.erase(i);
}
+ // No cache hit. See if an identical request is currently in flight.
+ CertVerifierJob* job;
+ std::map<RequestParams, CertVerifierJob*>::const_iterator j;
+ j = inflight_.find(key);
+ if (j != inflight_.end()) {
+ // An identical request is in flight already. We'll just attach our
+ // callback.
+ inflight_joins_++;
+ job = j->second;
+ } else {
+ // Need to make a new request.
+ CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags,
+ this);
+ job = new CertVerifierJob(worker);
+ inflight_.insert(std::make_pair(key, job));
+ if (!worker->Start()) {
+ inflight_.erase(key);
+ delete job;
+ delete worker;
+ *out_req = NULL;
+ return ERR_FAILED; // TODO(wtc): Log an error message.
+ }
+ }
+
+ CertVerifierRequest* request =
+ new CertVerifierRequest(callback, verify_result);
+ job->AddRequest(request);
+ *out_req = request;
return ERR_IO_PENDING;
}
+void CertVerifier::CancelRequest(RequestHandle req) {
+ DCHECK(CalledOnValidThread());
+ CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
+ request->Cancel();
+}
+
+void CertVerifier::ClearCache() {
+ DCHECK(CalledOnValidThread());
+
+ cache_.clear();
+ // Leaves inflight_ alone.
+}
+
+size_t CertVerifier::GetCacheSize() const {
+ DCHECK(CalledOnValidThread());
+
+ return cache_.size();
+}
+
+// HandleResult is called by CertVerifierWorker on the origin message loop.
+// It deletes CertVerifierJob.
+void CertVerifier::HandleResult(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ int error,
+ const CertVerifyResult& verify_result) {
+ DCHECK(CalledOnValidThread());
+
+ const base::Time current_time(time_service_->Now());
+
+ CachedCertVerifyResult cached_result;
+ cached_result.error = error;
+ cached_result.result = verify_result;
+ uint32 ttl = kTTLSecs;
+ cached_result.expiry = current_time + base::TimeDelta::FromSeconds(ttl);
+
+ const RequestParams key = {cert->fingerprint(), hostname, flags};
+
+ DCHECK_GE(kMaxCacheEntries, 1u);
+ DCHECK_LE(cache_.size(), kMaxCacheEntries);
+ if (cache_.size() == kMaxCacheEntries) {
+ // Need to remove an element of the cache.
+ std::map<RequestParams, CachedCertVerifyResult>::iterator i, cur;
+ for (i = cache_.begin(); i != cache_.end(); ) {
+ cur = i++;
+ if (cur->second.HasExpired(current_time))
+ cache_.erase(cur);
+ }
+ }
+ if (cache_.size() == kMaxCacheEntries) {
+ // If we didn't clear out any expired entries, we just remove the first
+ // element. Crummy but simple.
+ cache_.erase(cache_.begin());
+ }
+
+ cache_.insert(std::make_pair(key, cached_result));
+
+ std::map<RequestParams, CertVerifierJob*>::iterator j;
+ j = inflight_.find(key);
+ if (j == inflight_.end()) {
+ NOTREACHED();
+ return;
+ }
+ CertVerifierJob* job = j->second;
+ inflight_.erase(j);
+
+ job->HandleResult(cached_result);
+ delete job;
+}
+
+/////////////////////////////////////////////////////////////////////
+
+SingleRequestCertVerifier::SingleRequestCertVerifier(
+ CertVerifier* cert_verifier)
+ : cert_verifier_(cert_verifier),
+ cur_request_(NULL),
+ cur_request_callback_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ callback_(this, &SingleRequestCertVerifier::OnVerifyCompletion)) {
+ DCHECK(cert_verifier_ != NULL);
+}
+
+SingleRequestCertVerifier::~SingleRequestCertVerifier() {
+ if (cur_request_) {
+ cert_verifier_->CancelRequest(cur_request_);
+ cur_request_ = NULL;
+ }
+}
+
+int SingleRequestCertVerifier::Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CertVerifyResult* verify_result,
+ CompletionCallback* callback) {
+ // Should not be already in use.
+ DCHECK(!cur_request_ && !cur_request_callback_);
+
+ // Do a synchronous verification.
+ if (!callback)
+ return cert->Verify(hostname, flags, verify_result);
+
+ CertVerifier::RequestHandle request = NULL;
+
+ // We need to be notified of completion before |callback| is called, so that
+ // we can clear out |cur_request_*|.
+ int rv = cert_verifier_->Verify(
+ cert, hostname, flags, verify_result, &callback_, &request);
+
+ if (rv == ERR_IO_PENDING) {
+ // Cleared in OnVerifyCompletion().
+ cur_request_ = request;
+ cur_request_callback_ = callback;
+ }
+
+ return rv;
+}
+
+void SingleRequestCertVerifier::OnVerifyCompletion(int result) {
+ DCHECK(cur_request_ && cur_request_callback_);
+
+ CompletionCallback* callback = cur_request_callback_;
+
+ // Clear the outstanding request information.
+ cur_request_ = NULL;
+ cur_request_callback_ = NULL;
+
+ // Call the user's original callback.
+ callback->Run(result);
+}
+
} // namespace net
+
+DISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker);
+
diff --git a/net/base/cert_verifier.h b/net/base/cert_verifier.h
index 791f8d3..3d19abb 100644
--- a/net/base/cert_verifier.h
+++ b/net/base/cert_verifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-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.
@@ -6,29 +6,68 @@
#define NET_BASE_CERT_VERIFIER_H_
#pragma once
+#include <map>
#include <string>
#include "base/basictypes.h"
-#include "base/ref_counted.h"
+#include "base/non_thread_safe.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/base/x509_cert_types.h"
namespace net {
-class CertVerifyResult;
+class CertVerifierJob;
+class CertVerifierWorker;
class X509Certificate;
-// This class represents the task of verifying a certificate. It can only
-// verify a single certificate at a time, so if you need to verify multiple
-// certificates at the same time, you will need to allocate a CertVerifier
-// object for each certificate.
+// CachedCertVerifyResult contains the result of a certificate verification.
+struct CachedCertVerifyResult {
+ CachedCertVerifyResult();
+ ~CachedCertVerifyResult();
+
+ int error; // The return value of CertVerifier::Verify.
+ CertVerifyResult result; // The output of CertVerifier::Verify.
+
+ // The time at which the certificate verification result expires.
+ base::Time expiry;
+
+ // Returns true if |current_time| is greater than or equal to |expiry|.
+ bool HasExpired(base::Time current_time) const;
+};
+
+// CertVerifier represents a service for verifying certificates.
//
-class CertVerifier {
+// CertVerifier can handle multiple requests at a time, so when canceling a
+// request the RequestHandle that was returned by Verify() needs to be
+// given. A simpler alternative for consumers that only have 1 outstanding
+// request at a time is to create a SingleRequestCertVerifier wrapper around
+// CertVerifier (which will automatically cancel the single request when it
+// goes out of scope).
+class CertVerifier : public NonThreadSafe {
public:
+ // Opaque type used to cancel a request.
+ typedef void* RequestHandle;
+
+ // CertVerifier must not call base::Time::Now() directly. It must call
+ // time_service_->Now(). This allows unit tests to mock the current time.
+ class TimeService {
+ public:
+ virtual ~TimeService() {}
+
+ virtual base::Time Now() = 0;
+ };
+
CertVerifier();
- // If a completion callback is pending when the verifier is destroyed, the
- // certificate verification is cancelled, and the completion callback will
- // not be called.
+ // Used by unit tests to mock the current time. Takes ownership of
+ // |time_service|.
+ explicit CertVerifier(TimeService* time_service);
+
+ // When the verifier is destroyed, all certificate verifications requests are
+ // canceled, and their completion callbacks will not be called.
~CertVerifier();
// Verifies the given certificate against the given hostname. Returns OK if
@@ -49,23 +88,128 @@ class CertVerifier {
// VERIFY_REV_CHECKING_ENABLED is not set), EV certificate verification will
// not be performed.
//
- // When callback is null, the operation completes synchronously.
- //
- // When callback is non-null, ERR_IO_PENDING is returned if the operation
+ // |callback| must not be null. ERR_IO_PENDING is returned if the operation
// could not be completed synchronously, in which case the result code will
// be passed to the callback when available.
//
- int Verify(X509Certificate* cert, const std::string& hostname,
- int flags, CertVerifyResult* verify_result,
- CompletionCallback* callback);
+ // If |out_req| is non-NULL, then |*out_req| will be filled with a handle to
+ // the async request. This handle is not valid after the request has
+ // completed.
+ int Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CertVerifyResult* verify_result,
+ CompletionCallback* callback,
+ RequestHandle* out_req);
+
+ // Cancels the specified request. |req| is the handle returned by Verify().
+ // After a request is canceled, its completion callback will not be called.
+ void CancelRequest(RequestHandle req);
+
+ // Clears the verification result cache.
+ void ClearCache();
+
+ size_t GetCacheSize() const;
+
+ uint64 requests() const { return requests_; }
+ uint64 cache_hits() const { return cache_hits_; }
+ uint64 inflight_joins() const { return inflight_joins_; }
private:
- class Request;
- friend class Request;
- scoped_refptr<Request> request_;
+ friend class CertVerifierWorker; // Calls HandleResult.
+
+ // Input parameters of a certificate verification request.
+ struct RequestParams {
+ bool operator==(const RequestParams& other) const {
+ // |flags| is compared before |cert_fingerprint| and |hostname| under
+ // assumption that integer comparisons are faster than memory and string
+ // comparisons.
+ return (flags == other.flags &&
+ memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
+ sizeof(cert_fingerprint.data)) == 0 &&
+ hostname == other.hostname);
+ }
+
+ bool operator<(const RequestParams& other) const {
+ // |flags| is compared before |cert_fingerprint| and |hostname| under
+ // assumption that integer comparisons are faster than memory and string
+ // comparisons.
+ if (flags != other.flags)
+ return flags < other.flags;
+ int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
+ sizeof(cert_fingerprint.data));
+ if (rv != 0)
+ return rv < 0;
+ return hostname < other.hostname;
+ }
+
+ SHA1Fingerprint cert_fingerprint;
+ std::string hostname;
+ int flags;
+ };
+
+ void HandleResult(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ int error,
+ const CertVerifyResult& verify_result);
+
+ // cache_ maps from a request to a cached result. The cached result may
+ // have expired and the size of |cache_| must be <= kMaxCacheEntries.
+ std::map<RequestParams, CachedCertVerifyResult> cache_;
+
+ // inflight_ maps from a request to an active verification which is taking
+ // place.
+ std::map<RequestParams, CertVerifierJob*> inflight_;
+
+ scoped_ptr<TimeService> time_service_;
+
+ uint64 requests_;
+ uint64 cache_hits_;
+ uint64 inflight_joins_;
+
DISALLOW_COPY_AND_ASSIGN(CertVerifier);
};
+// This class represents the task of verifying a certificate. It wraps
+// CertVerifier to verify only a single certificate at a time and cancels this
+// request when going out of scope.
+class SingleRequestCertVerifier {
+ public:
+ // |cert_verifier| must remain valid for the lifetime of |this|.
+ explicit SingleRequestCertVerifier(CertVerifier* cert_verifier);
+
+ // If a completion callback is pending when the verifier is destroyed, the
+ // certificate verification is canceled, and the completion callback will
+ // not be called.
+ ~SingleRequestCertVerifier();
+
+ // Verifies the given certificate, filling out the |verify_result| object
+ // upon success. See CertVerifier::Verify() for details.
+ int Verify(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CertVerifyResult* verify_result,
+ CompletionCallback* callback);
+
+ private:
+ // Callback for when the request to |cert_verifier_| completes, so we
+ // dispatch to the user's callback.
+ void OnVerifyCompletion(int result);
+
+ // The actual certificate verifier that will handle the request.
+ CertVerifier* const cert_verifier_;
+
+ // The current request (if any).
+ CertVerifier::RequestHandle cur_request_;
+ CompletionCallback* cur_request_callback_;
+
+ // Completion callback for when request to |cert_verifier_| completes.
+ net::CompletionCallbackImpl<SingleRequestCertVerifier> callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(SingleRequestCertVerifier);
+};
+
} // namespace net
#endif // NET_BASE_CERT_VERIFIER_H_
diff --git a/net/base/cert_verifier_unittest.cc b/net/base/cert_verifier_unittest.cc
new file mode 100644
index 0000000..ca5e1f4
--- /dev/null
+++ b/net/base/cert_verifier_unittest.cc
@@ -0,0 +1,260 @@
+// 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/base/cert_verifier.h"
+
+#include "base/callback.h"
+#include "base/file_path.h"
+#include "base/stringprintf.h"
+#include "net/base/cert_test_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/base/x509_certificate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class TestTimeService : public CertVerifier::TimeService {
+ public:
+ // CertVerifier::TimeService methods:
+ virtual base::Time Now() { return current_time_; }
+
+ void set_current_time(base::Time now) { current_time_ = now; }
+
+ private:
+ base::Time current_time_;
+};
+
+class CertVerifierTest : public testing::Test {
+};
+
+class ExplodingCallback : public CallbackRunner<Tuple1<int> > {
+ public:
+ virtual void RunWithParams(const Tuple1<int>& params) {
+ FAIL();
+ }
+};
+
+// Tests a cache hit, which should results in synchronous completion.
+TEST_F(CertVerifierTest, CacheHit) {
+ TestTimeService* time_service = new TestTimeService;
+ base::Time current_time = base::Time::Now();
+ time_service->set_current_time(current_time);
+ CertVerifier verifier(time_service);
+
+ FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> google_cert(
+ ImportCertFromFile(certs_dir, "google.single.der"));
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert);
+
+ int error;
+ CertVerifyResult verify_result;
+ TestCompletionCallback callback;
+ CertVerifier::RequestHandle request_handle;
+
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(1u, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ // Synchronous completion.
+ ASSERT_NE(ERR_IO_PENDING, error);
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_TRUE(request_handle == NULL);
+ ASSERT_EQ(2u, verifier.requests());
+ ASSERT_EQ(1u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+}
+
+// Tests an inflight join.
+TEST_F(CertVerifierTest, InflightJoin) {
+ TestTimeService* time_service = new TestTimeService;
+ base::Time current_time = base::Time::Now();
+ time_service->set_current_time(current_time);
+ CertVerifier verifier(time_service);
+
+ FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> google_cert(
+ ImportCertFromFile(certs_dir, "google.single.der"));
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert);
+
+ int error;
+ CertVerifyResult verify_result;
+ TestCompletionCallback callback;
+ CertVerifier::RequestHandle request_handle;
+ CertVerifyResult verify_result2;
+ TestCompletionCallback callback2;
+ CertVerifier::RequestHandle request_handle2;
+
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result2,
+ &callback2, &request_handle2);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle2 != NULL);
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ error = callback2.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(2u, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(1u, verifier.inflight_joins());
+}
+
+// Tests cache entry expiration.
+TEST_F(CertVerifierTest, ExpiredCacheEntry) {
+ TestTimeService* time_service = new TestTimeService;
+ base::Time current_time = base::Time::Now();
+ time_service->set_current_time(current_time);
+ CertVerifier verifier(time_service);
+
+ FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> google_cert(
+ ImportCertFromFile(certs_dir, "google.single.der"));
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert);
+
+ int error;
+ CertVerifyResult verify_result;
+ TestCompletionCallback callback;
+ CertVerifier::RequestHandle request_handle;
+
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(1u, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+
+ // Before expiration, should have a cache hit.
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ // Synchronous completion.
+ ASSERT_NE(ERR_IO_PENDING, error);
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_TRUE(request_handle == NULL);
+ ASSERT_EQ(2u, verifier.requests());
+ ASSERT_EQ(1u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+
+ // After expiration, should not have a cache hit.
+ ASSERT_EQ(1u, verifier.GetCacheSize());
+ current_time += base::TimeDelta::FromMinutes(60);
+ time_service->set_current_time(current_time);
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ ASSERT_EQ(0u, verifier.GetCacheSize());
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(3u, verifier.requests());
+ ASSERT_EQ(1u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+}
+
+// Tests a full cache.
+TEST_F(CertVerifierTest, FullCache) {
+ TestTimeService* time_service = new TestTimeService;
+ base::Time current_time = base::Time::Now();
+ time_service->set_current_time(current_time);
+ CertVerifier verifier(time_service);
+
+ FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> google_cert(
+ ImportCertFromFile(certs_dir, "google.single.der"));
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert);
+
+ int error;
+ CertVerifyResult verify_result;
+ TestCompletionCallback callback;
+ CertVerifier::RequestHandle request_handle;
+
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(1u, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+
+ const unsigned kCacheSize = 256;
+
+ for (unsigned i = 0; i < kCacheSize; i++) {
+ std::string hostname = base::StringPrintf("www%d.example.com", i + 1);
+ error = verifier.Verify(google_cert, hostname, 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ }
+ ASSERT_EQ(kCacheSize + 1, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+
+ ASSERT_EQ(kCacheSize, verifier.GetCacheSize());
+ current_time += base::TimeDelta::FromMinutes(60);
+ time_service->set_current_time(current_time);
+ error = verifier.Verify(google_cert, "www999.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ ASSERT_EQ(kCacheSize, verifier.GetCacheSize());
+ error = callback.WaitForResult();
+ ASSERT_EQ(1u, verifier.GetCacheSize());
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(kCacheSize + 2, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+}
+
+// Tests that the callback of a canceled request is never made.
+TEST_F(CertVerifierTest, CancelRequest) {
+ CertVerifier verifier;
+
+ FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> google_cert(
+ ImportCertFromFile(certs_dir, "google.single.der"));
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert);
+
+ int error;
+ CertVerifyResult verify_result;
+ ExplodingCallback exploding_callback;
+ CertVerifier::RequestHandle request_handle;
+
+ error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result,
+ &exploding_callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ verifier.CancelRequest(request_handle);
+
+ // Issue a few more requests to the worker pool and wait for their
+ // completion, so that the task of the canceled request (which runs on a
+ // worker thread) is likely to complete by the end of this test.
+ TestCompletionCallback callback;
+ for (int i = 0; i < 5; ++i) {
+ error = verifier.Verify(google_cert, "www2.example.com", 0, &verify_result,
+ &callback, &request_handle);
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ verifier.ClearCache();
+ }
+}
+
+} // namespace net
diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc
index 1bb2d01..76589c7 100644
--- a/net/base/cookie_monster.cc
+++ b/net/base/cookie_monster.cc
@@ -407,7 +407,15 @@ void CookieMonster::SetExpiryAndKeyScheme(ExpiryAndKeyScheme key_scheme) {
expiry_and_key_scheme_ = key_scheme;
}
+<<<<<<< HEAD
#if defined(ANDROID)
+=======
+void CookieMonster::SetClearPersistentStoreOnExit(bool clear_local_store) {
+ if(store_)
+ store_->SetClearLocalStateOnExit(clear_local_store);
+}
+
+>>>>>>> chromium.org at r10.0.621.0
void CookieMonster::FlushStore(Task* completion_task) {
AutoLock autolock(lock_);
if (initialized_ && store_)
@@ -415,7 +423,10 @@ void CookieMonster::FlushStore(Task* completion_task) {
else if (completion_task)
MessageLoop::current()->PostTask(FROM_HERE, completion_task);
}
+<<<<<<< HEAD
#endif
+=======
+>>>>>>> chromium.org at r10.0.621.0
// The system resolution is not high enough, so we can have multiple
// set cookies that result in the same system time. When this happens, we
@@ -1329,7 +1340,11 @@ void CookieMonster::DeleteCookie(const GURL& url,
}
}
-CookieMonster::CookieList CookieMonster::GetAllCookies() {
+CookieMonster* CookieMonster::GetCookieMonster() {
+ return this;
+}
+
+CookieList CookieMonster::GetAllCookies() {
AutoLock autolock(lock_);
InitIfNecessary();
@@ -1362,13 +1377,12 @@ CookieMonster::CookieList CookieMonster::GetAllCookies() {
return cookie_list;
}
-CookieMonster::CookieList CookieMonster::GetAllCookiesForURL(const GURL& url) {
+CookieList CookieMonster::GetAllCookiesForURLWithOptions(
+ const GURL& url,
+ const CookieOptions& options) {
AutoLock autolock(lock_);
InitIfNecessary();
- CookieOptions options;
- options.set_include_httponly();
-
std::vector<CanonicalCookie*> cookie_ptrs;
FindCookiesForHostAndDomain(url, options, false, &cookie_ptrs);
std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
@@ -1381,6 +1395,13 @@ CookieMonster::CookieList CookieMonster::GetAllCookiesForURL(const GURL& url) {
return cookies;
}
+CookieList CookieMonster::GetAllCookiesForURL(const GURL& url) {
+ CookieOptions options;
+ options.set_include_httponly();
+
+ return GetAllCookiesForURLWithOptions(url, options);
+}
+
void CookieMonster::FindCookiesForHostAndDomain(
const GURL& url,
const CookieOptions& options,
diff --git a/net/base/cookie_monster.h b/net/base/cookie_monster.h
index b168eb8..2c66554 100644
--- a/net/base/cookie_monster.h
+++ b/net/base/cookie_monster.h
@@ -30,6 +30,8 @@ class Histogram;
namespace net {
+class CookieList;
+
// The cookie monster is the system for storing and retrieving cookies. It has
// an in-memory list of all cookies, and synchronizes non-session cookies to an
// optional permanent storage that implements the PersistentCookieStore
@@ -95,7 +97,6 @@ class CookieMonster : public CookieStore {
// subtantially more entries in the map.
typedef std::multimap<std::string, CanonicalCookie*> CookieMap;
typedef std::pair<CookieMap::iterator, CookieMap::iterator> CookieMapItPair;
- typedef std::vector<CanonicalCookie> CookieList;
// The key and expiry scheme to be used by the monster.
// EKS_KEEP_RECENT_AND_PURGE_ETLDP1 means to use
@@ -146,7 +147,7 @@ class CookieMonster : public CookieStore {
// Deletes all cookies with that might apply to |url| that has |cookie_name|.
virtual void DeleteCookie(const GURL& url, const std::string& cookie_name);
- virtual CookieMonster* GetCookieMonster() { return this; }
+ virtual CookieMonster* GetCookieMonster();
// Sets a cookie given explicit user-provided cookie attributes. The cookie
// name, value, domain, etc. are each provided as separate strings. This
@@ -169,10 +170,15 @@ class CookieMonster : public CookieStore {
CookieList GetAllCookies();
// Returns all the cookies, for use in management UI, etc. Filters results
- // using given url scheme, host / domain and path. This does not mark the
- // cookies as having been accessed.
+ // using given url scheme, host / domain and path and options. This does not
+ // mark the cookies as having been accessed.
// The returned cookies are ordered by longest path, then earliest
// creation date.
+ CookieList GetAllCookiesForURLWithOptions(const GURL& url,
+ const CookieOptions& options);
+
+ // Invokes GetAllCookiesForURLWithOptions with options set to include HTTP
+ // only cookies.
CookieList GetAllCookiesForURL(const GURL& url);
// Deletes all of the cookies.
@@ -207,6 +213,10 @@ class CookieMonster : public CookieStore {
// function must be called before initialization.
void SetExpiryAndKeyScheme(ExpiryAndKeyScheme key_scheme);
+ // Delegates the call to set the |clear_local_store_on_exit_| flag of the
+ // PersistentStore if it exists.
+ void SetClearPersistentStoreOnExit(bool clear_local_store);
+
// There are some unknowns about how to correctly handle file:// cookies,
// and our implementation for this is not robust enough. This allows you
// to enable support, but it should only be used for testing. Bug 1157243.
@@ -214,14 +224,20 @@ class CookieMonster : public CookieStore {
static void EnableFileScheme();
static bool enable_file_scheme_;
+<<<<<<< HEAD
#if defined(ANDROID)
+=======
+>>>>>>> chromium.org at r10.0.621.0
// Flush the backing store (if any) to disk and post the given task when done.
// WARNING: THE CALLBACK WILL RUN ON A RANDOM THREAD. IT MUST BE THREAD SAFE.
// It may be posted to the current thread, or it may run on the thread that
// actually does the flushing. Your Task should generally post a notification
// to the thread you actually want to be notified on.
void FlushStore(Task* completion_task);
+<<<<<<< HEAD
#endif
+=======
+>>>>>>> chromium.org at r10.0.621.0
private:
~CookieMonster();
@@ -692,15 +708,22 @@ typedef base::RefCountedThreadSafe<CookieMonster::PersistentCookieStore>
class CookieMonster::PersistentCookieStore
: public RefcountedPersistentCookieStore {
public:
- virtual ~PersistentCookieStore() { }
+ virtual ~PersistentCookieStore() {}
// Initializes the store and retrieves the existing cookies. This will be
// called only once at startup.
- virtual bool Load(std::vector<CookieMonster::CanonicalCookie*>*) = 0;
+ virtual bool Load(std::vector<CookieMonster::CanonicalCookie*>* cookies) = 0;
+
+ virtual void AddCookie(const CanonicalCookie& cc) = 0;
+ virtual void UpdateCookieAccessTime(const CanonicalCookie& cc) = 0;
+ virtual void DeleteCookie(const CanonicalCookie& cc) = 0;
- virtual void AddCookie(const CanonicalCookie&) = 0;
- virtual void UpdateCookieAccessTime(const CanonicalCookie&) = 0;
- virtual void DeleteCookie(const CanonicalCookie&) = 0;
+ // Sets the value of the user preference whether the persistent storage
+ // must be deleted upon destruction.
+ virtual void SetClearLocalStateOnExit(bool clear_local_state) = 0;
+
+ // Flush the store and post the given Task when complete.
+ virtual void Flush(Task* completion_task) = 0;
#if defined(ANDROID)
// Flush the store and post the given Task when complete.
@@ -708,12 +731,15 @@ class CookieMonster::PersistentCookieStore
#endif
protected:
- PersistentCookieStore() { }
+ PersistentCookieStore() {}
private:
DISALLOW_COPY_AND_ASSIGN(PersistentCookieStore);
};
+class CookieList : public std::vector<CookieMonster::CanonicalCookie> {
+};
+
} // namespace net
#endif // NET_BASE_COOKIE_MONSTER_H_
diff --git a/net/base/cookie_monster_store_test.h b/net/base/cookie_monster_store_test.h
index 8a21930..84ead74 100644
--- a/net/base/cookie_monster_store_test.h
+++ b/net/base/cookie_monster_store_test.h
@@ -7,6 +7,7 @@
// that need to test out CookieMonster interactions with the backing store.
// It should only be included by test code.
+#include "base/message_loop.h"
#include "base/time.h"
#include "net/base/cookie_monster.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -66,6 +67,14 @@ class MockPersistentCookieStore
CookieStoreCommand(CookieStoreCommand::REMOVE, cookie));
}
+ virtual void Flush(Task* completion_task) {
+ if (completion_task)
+ MessageLoop::current()->PostTask(FROM_HERE, completion_task);
+ }
+
+ // No files are created so nothing to clear either
+ virtual void SetClearLocalStateOnExit(bool clear_local_state) {}
+
void SetLoadExpectation(
bool return_value,
const std::vector<net::CookieMonster::CanonicalCookie*>& result) {
@@ -185,6 +194,13 @@ class MockSimplePersistentCookieStore
cookies_.erase(it);
}
+ virtual void Flush(Task* completion_task) {
+ if (completion_task)
+ MessageLoop::current()->PostTask(FROM_HERE, completion_task);
+ }
+
+ virtual void SetClearLocalStateOnExit(bool clear_local_state) {}
+
private:
CanonicalCookieMap cookies_;
};
diff --git a/net/base/cookie_monster_unittest.cc b/net/base/cookie_monster_unittest.cc
index 6fce2a0..a0c16ea 100644
--- a/net/base/cookie_monster_unittest.cc
+++ b/net/base/cookie_monster_unittest.cc
@@ -1003,7 +1003,7 @@ TEST(CookieMonsterTest, TestSecure) {
}
static Time GetFirstCookieAccessDate(net::CookieMonster* cm) {
- const net::CookieMonster::CookieList all_cookies(cm->GetAllCookies());
+ const net::CookieList all_cookies(cm->GetAllCookies());
return all_cookies.front().LastAccessDate();
}
@@ -1138,8 +1138,8 @@ TEST(CookieMonsterTest, NetUtilCookieTest) {
static bool FindAndDeleteCookie(net::CookieMonster* cm,
const std::string& domain,
const std::string& name) {
- net::CookieMonster::CookieList cookies = cm->GetAllCookies();
- for (net::CookieMonster::CookieList::iterator it = cookies.begin();
+ net::CookieList cookies = cm->GetAllCookies();
+ for (net::CookieList::iterator it = cookies.begin();
it != cookies.end(); ++it)
if (it->Domain() == domain && it->Name() == name)
return cm->DeleteCanonicalCookie(*it);
@@ -1204,9 +1204,8 @@ TEST(CookieMonsterTest, GetAllCookiesForURL) {
PlatformThread::Sleep(kLastAccessThresholdMilliseconds + 20);
// Check cookies for url.
- net::CookieMonster::CookieList cookies =
- cm->GetAllCookiesForURL(url_google);
- net::CookieMonster::CookieList::iterator it = cookies.begin();
+ net::CookieList cookies = cm->GetAllCookiesForURL(url_google);
+ net::CookieList::iterator it = cookies.begin();
ASSERT_TRUE(it != cookies.end());
EXPECT_EQ("www.google.izzle", it->Domain());
@@ -1218,6 +1217,17 @@ TEST(CookieMonsterTest, GetAllCookiesForURL) {
ASSERT_TRUE(++it == cookies.end());
+ // Check cookies for url excluding http-only cookies.
+ cookies =
+ cm->GetAllCookiesForURLWithOptions(url_google, net::CookieOptions());
+ it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ(".google.izzle", it->Domain());
+ EXPECT_EQ("C", it->Name());
+
+ ASSERT_TRUE(++it == cookies.end());
+
// Test secure cookies.
cookies = cm->GetAllCookiesForURL(url_google_secure);
it = cookies.begin();
@@ -1258,9 +1268,8 @@ TEST(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
"E=F;",
options));
- net::CookieMonster::CookieList cookies =
- cm->GetAllCookiesForURL(url_google_foo);
- net::CookieMonster::CookieList::iterator it = cookies.begin();
+ net::CookieList cookies = cm->GetAllCookiesForURL(url_google_foo);
+ net::CookieList::iterator it = cookies.begin();
ASSERT_TRUE(it != cookies.end());
EXPECT_EQ("A", it->Name());
@@ -1299,10 +1308,10 @@ TEST(CookieMonsterTest, DeleteCookieByName) {
cm->DeleteCookie(GURL(std::string(kUrlGoogle) + "/foo/bar"), "A");
- net::CookieMonster::CookieList cookies = cm->GetAllCookies();
+ net::CookieList cookies = cm->GetAllCookies();
size_t expected_size = 4;
EXPECT_EQ(expected_size, cookies.size());
- for (net::CookieMonster::CookieList::iterator it = cookies.begin();
+ for (net::CookieList::iterator it = cookies.begin();
it != cookies.end(); ++it) {
EXPECT_NE("A1", it->Value());
EXPECT_NE("A2", it->Value());
@@ -1494,7 +1503,7 @@ TEST(CookieMonsterTest, DontImportDuplicateCreationTimes) {
scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
- net::CookieMonster::CookieList list(cm->GetAllCookies());
+ net::CookieList list(cm->GetAllCookies());
EXPECT_EQ(2U, list.size());
// Confirm that we have one of each.
std::string name1(list[0].Name());
@@ -1617,9 +1626,8 @@ TEST(CookieMonsterTest, SetCookieWithDetails) {
url_google_foo, "A=", "B", std::string(), "foo", base::Time(),
false, false));
- net::CookieMonster::CookieList cookies =
- cm->GetAllCookiesForURL(url_google_foo);
- net::CookieMonster::CookieList::iterator it = cookies.begin();
+ net::CookieList cookies = cm->GetAllCookiesForURL(url_google_foo);
+ net::CookieList::iterator it = cookies.begin();
ASSERT_TRUE(it != cookies.end());
EXPECT_EQ("A", it->Name());
@@ -1771,10 +1779,10 @@ TEST(CookieMonsterTest, UniqueCreationTime) {
".google.com", "/", Time(), false, false);
// Now we check
- net::CookieMonster::CookieList cookie_list(cm->GetAllCookies());
+ net::CookieList cookie_list(cm->GetAllCookies());
typedef std::map<int64, net::CookieMonster::CanonicalCookie> TimeCookieMap;
TimeCookieMap check_map;
- for (net::CookieMonster::CookieList::const_iterator it = cookie_list.begin();
+ for (net::CookieList::const_iterator it = cookie_list.begin();
it != cookie_list.end(); it++) {
const int64 creation_date = it->CreationDate().ToInternalValue();
TimeCookieMap::const_iterator
@@ -1867,7 +1875,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));
- CookieMonster::CookieList cookies(cmin->GetAllCookies());
+ CookieList cookies(cmin->GetAllCookies());
ASSERT_EQ(2u, cookies.size());
// Ordering is path length, then creation time. So second cookie
// will come first, and we need to swap them.
@@ -1914,7 +1922,7 @@ TEST(CookieMonsterTest, CookieOrdering) {
CookieOptions()));
{
unsigned int i = 0;
- CookieMonster::CookieList cookies(cm->GetAllCookiesForURL(
+ CookieList cookies(cm->GetAllCookiesForURL(
GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
ASSERT_EQ(5u, cookies.size());
EXPECT_EQ("d", cookies[i++].Name());
@@ -1926,7 +1934,7 @@ TEST(CookieMonsterTest, CookieOrdering) {
{
unsigned int i = 0;
- CookieMonster::CookieList cookies(cm->GetAllCookies());
+ CookieList cookies(cm->GetAllCookies());
ASSERT_EQ(6u, cookies.size());
EXPECT_EQ("d", cookies[i++].Name());
EXPECT_EQ("a", cookies[i++].Name());
@@ -2047,7 +2055,7 @@ TEST(CookieMonsterTest, ForceSessionOnly) {
options));
// Get the canonical cookie.
- CookieMonster::CookieList cookie_list = cm->GetAllCookies();
+ CookieList cookie_list = cm->GetAllCookies();
ASSERT_EQ(1U, cookie_list.size());
ASSERT_FALSE(cookie_list[0].IsPersistent());
@@ -2061,4 +2069,108 @@ TEST(CookieMonsterTest, ForceSessionOnly) {
ASSERT_EQ(0U, cookie_list.size());
}
+namespace {
+
+// Mock PersistentCookieStore that keeps track of the number of Flush() calls.
+class FlushablePersistentStore : public CookieMonster::PersistentCookieStore {
+ public:
+ FlushablePersistentStore() : flush_count_(0) {}
+
+ bool Load(std::vector<CookieMonster::CanonicalCookie*>*) {
+ return false;
+ }
+
+ void AddCookie(const CookieMonster::CanonicalCookie&) {}
+ void UpdateCookieAccessTime(const CookieMonster::CanonicalCookie&) {}
+ void DeleteCookie(const CookieMonster::CanonicalCookie&) {}
+ void SetClearLocalStateOnExit(bool clear_local_state) {}
+
+ void Flush(Task* completion_callback) {
+ ++flush_count_;
+ if (completion_callback) {
+ completion_callback->Run();
+ delete completion_callback;
+ }
+ }
+
+ int flush_count() {
+ return flush_count_;
+ }
+
+ private:
+ volatile int flush_count_;
+};
+
+// Counts the number of times Callback() has been run.
+class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> {
+ public:
+ CallbackCounter() : callback_count_(0) {}
+
+ void Callback() {
+ ++callback_count_;
+ }
+
+ int callback_count() {
+ return callback_count_;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<CallbackCounter>;
+ volatile int callback_count_;
+};
+
+} // namespace
+
+// Test that FlushStore() is forwarded to the store and callbacks are posted.
+TEST(CookieMonsterTest, FlushStore) {
+ scoped_refptr<CallbackCounter> counter(new CallbackCounter());
+ scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
+
+ ASSERT_EQ(0, store->flush_count());
+ ASSERT_EQ(0, counter->callback_count());
+
+ // Before initialization, FlushStore() should just run the callback.
+ cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(0, store->flush_count());
+ ASSERT_EQ(1, counter->callback_count());
+
+ // NULL callback is safe.
+ cm->FlushStore(NULL);
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(0, store->flush_count());
+ ASSERT_EQ(1, counter->callback_count());
+
+ // After initialization, FlushStore() should delegate to the store.
+ cm->GetAllCookies(); // Force init.
+ cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(1, store->flush_count());
+ ASSERT_EQ(2, counter->callback_count());
+
+ // NULL callback is still safe.
+ cm->FlushStore(NULL);
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(2, store->flush_count());
+ ASSERT_EQ(2, counter->callback_count());
+
+ // If there's no backing store, FlushStore() is always a safe no-op.
+ cm = new net::CookieMonster(NULL, NULL);
+ cm->GetAllCookies(); // Force init.
+ cm->FlushStore(NULL);
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(2, counter->callback_count());
+
+ cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(3, counter->callback_count());
+}
+
} // namespace
diff --git a/net/base/data_url.cc b/net/base/data_url.cc
index e30f7da..e387cd1 100644
--- a/net/base/data_url.cc
+++ b/net/base/data_url.cc
@@ -60,6 +60,10 @@ bool DataURL::Parse(const GURL& url, std::string* mime_type,
if (charset->empty())
charset->assign("US-ASCII");
+ // The caller may not be interested in receiving the data.
+ if (!data)
+ return true;
+
// Preserve spaces if dealing with text or xml input, same as mozilla:
// https://bugzilla.mozilla.org/show_bug.cgi?id=138052
// but strip them otherwise:
diff --git a/net/base/data_url.h b/net/base/data_url.h
index b40878a..65a211a 100644
--- a/net/base/data_url.h
+++ b/net/base/data_url.h
@@ -37,6 +37,9 @@ class DataURL {
// If the URL is malformed, then this method will return false, and its
// output variables will remain unchanged. On success, true is returned.
//
+ // OPTIONAL: If |data| is NULL, then the <data> section will not be parsed
+ // or validated.
+ //
static bool Parse(const GURL& url,
std::string* mime_type,
std::string* charset,
diff --git a/net/base/data_url_unittest.cc b/net/base/data_url_unittest.cc
index b7c2dc0..c90fb8b 100644
--- a/net/base/data_url_unittest.cc
+++ b/net/base/data_url_unittest.cc
@@ -9,13 +9,13 @@
namespace {
- struct ParseTestData {
- const char* url;
- bool is_valid;
- const char* mime_type;
- const char* charset;
- const char* data;
- };
+struct ParseTestData {
+ const char* url;
+ bool is_valid;
+ const char* mime_type;
+ const char* charset;
+ const char* data;
+};
class DataURLTest : public testing::Test {
};
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc
index 0a22d2b..61a2d65 100644
--- a/net/base/directory_lister.cc
+++ b/net/base/directory_lister.cc
@@ -11,6 +11,7 @@
#include "base/i18n/file_util_icu.h"
#include "base/message_loop.h"
#include "base/platform_thread.h"
+#include "base/thread_restrictions.h"
#include "net/base/net_errors.h"
namespace net {
@@ -122,6 +123,9 @@ DirectoryLister::DirectoryLister(const FilePath& dir,
DirectoryLister::~DirectoryLister() {
if (thread_) {
+ // This is a bug and we should stop joining this thread.
+ // http://crbug.com/65331
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
PlatformThread::Join(thread_);
}
}
@@ -147,6 +151,9 @@ void DirectoryLister::Cancel() {
canceled_.Set();
if (thread_) {
+ // This is a bug and we should stop joining this thread.
+ // http://crbug.com/65331
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
PlatformThread::Join(thread_);
thread_ = kNullThreadHandle;
}
diff --git a/net/base/directory_lister.h b/net/base/directory_lister.h
index 8623088..b531880 100644
--- a/net/base/directory_lister.h
+++ b/net/base/directory_lister.h
@@ -82,7 +82,7 @@ class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister>,
void set_delegate(DirectoryListerDelegate* d) { delegate_ = d; }
// PlatformThread::Delegate implementation
- void ThreadMain();
+ virtual void ThreadMain();
private:
friend class base::RefCountedThreadSafe<DirectoryLister>;
diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc
index 0c21857..ba9b42b 100644
--- a/net/base/dnsrr_resolver.cc
+++ b/net/base/dnsrr_resolver.cc
@@ -20,9 +20,6 @@
#include "net/base/dns_util.h"
#include "net/base/net_errors.h"
-DISABLE_RUNNABLE_METHOD_REFCOUNT(net::RRResolverWorker);
-DISABLE_RUNNABLE_METHOD_REFCOUNT(net::RRResolverHandle);
-
// Life of a query:
//
// DnsRRResolver RRResolverJob RRResolverWorker ... Handle
@@ -82,7 +79,7 @@ DISABLE_RUNNABLE_METHOD_REFCOUNT(net::RRResolverHandle);
namespace net {
static const uint16 kClassIN = 1;
-// kMaxCacheEntries is the number of RRResponse object that we'll cache.
+// kMaxCacheEntries is the number of RRResponse objects that we'll cache.
static const unsigned kMaxCacheEntries = 32;
// kNegativeTTLSecs is the number of seconds for which we'll cache a negative
// cache entry.
@@ -104,6 +101,7 @@ class RRResolverHandle {
// Cancel ensures that the result callback will never be made.
void Cancel() {
callback_ = NULL;
+ response_ = NULL;
}
// Post copies the contents of |response| to the caller's RRResponse and
@@ -118,11 +116,8 @@ class RRResolverHandle {
}
private:
- friend class RRResolverWorker;
- friend class DnsRRResolver;
-
CompletionCallback* callback_;
- RRResponse* const response_;
+ RRResponse* response_;
};
@@ -248,7 +243,7 @@ class RRResolverWorker {
Finish();
}
-#endif // OS_WIN
+#endif // OS_WIN
// HandleTestCases stuffs in magic test values in the event that the query is
// from a unittest.
@@ -277,8 +272,9 @@ class RRResolverWorker {
DCHECK_EQ(MessageLoop::current(), origin_loop_);
{
// We lock here because the worker thread could still be in Finished,
- // after the PostTask, but before unlocking |lock_|. In this case, we end
- // up deleting a locked Lock, which can lead to memory leaks.
+ // after the PostTask, but before unlocking |lock_|. If we do not lock in
+ // this case, we will end up deleting a locked Lock, which can lead to
+ // memory leaks or worse errors.
AutoLock locked(lock_);
if (!canceled_)
dnsrr_resolver_->HandleResult(name_, rrtype_, result_, response_);
@@ -453,12 +449,12 @@ class Buffer {
}
private:
- DISALLOW_COPY_AND_ASSIGN(Buffer);
-
const uint8* p_;
const uint8* const packet_;
unsigned len_;
const unsigned packet_len_;
+
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
};
bool RRResponse::HasExpired(const base::Time current_time) const {
@@ -558,12 +554,12 @@ bool RRResponse::ParseFromResponse(const uint8* p, unsigned len,
// lives only on the DnsRRResolver's origin message loop.
class RRResolverJob {
public:
- RRResolverJob(RRResolverWorker* worker)
+ explicit RRResolverJob(RRResolverWorker* worker)
: worker_(worker) {
}
~RRResolverJob() {
- Cancel(ERR_NAME_NOT_RESOLVED);
+ Cancel(ERR_ABORTED);
}
void AddHandle(RRResolverHandle* handle) {
@@ -579,9 +575,8 @@ class RRResolverJob {
if (worker_) {
worker_->Cancel();
worker_ = NULL;
+ PostAll(error, NULL);
}
-
- PostAll(error, NULL);
}
private:
@@ -699,11 +694,7 @@ void DnsRRResolver::OnIPAddressChanged() {
inflight.swap(inflight_);
cache_.clear();
- for (std::map<std::pair<std::string, uint16>, RRResolverJob*>::iterator
- i = inflight.begin(); i != inflight.end(); i++) {
- i->second->Cancel(ERR_ABORTED);
- delete i->second;
- }
+ STLDeleteValues(&inflight);
}
// HandleResult is called on the origin message loop.
@@ -718,12 +709,11 @@ void DnsRRResolver::HandleResult(const std::string& name, uint16 rrtype,
if (cache_.size() == kMaxCacheEntries) {
// need to remove an element of the cache.
const base::Time current_time(base::Time::Now());
- for (std::map<std::pair<std::string, uint16>, RRResponse>::iterator
- i = cache_.begin(); i != cache_.end(); ++i) {
- if (i->second.HasExpired(current_time)) {
- cache_.erase(i);
- break;
- }
+ std::map<std::pair<std::string, uint16>, RRResponse>::iterator i, cur;
+ for (i = cache_.begin(); i != cache_.end(); ) {
+ cur = i++;
+ if (cur->second.HasExpired(current_time))
+ cache_.erase(cur);
}
}
if (cache_.size() == kMaxCacheEntries) {
@@ -748,3 +738,6 @@ void DnsRRResolver::HandleResult(const std::string& name, uint16 rrtype,
}
} // namespace net
+
+DISABLE_RUNNABLE_METHOD_REFCOUNT(net::RRResolverHandle);
+DISABLE_RUNNABLE_METHOD_REFCOUNT(net::RRResolverWorker);
diff --git a/net/base/dnsrr_resolver.h b/net/base/dnsrr_resolver.h
index 64a1be5..30de5fe 100644
--- a/net/base/dnsrr_resolver.h
+++ b/net/base/dnsrr_resolver.h
@@ -19,8 +19,6 @@
#include "net/base/completion_callback.h"
#include "net/base/network_change_notifier.h"
-class MessageLoop;
-
namespace net {
// RRResponse contains the result of a successful request for a resource record.
@@ -57,7 +55,6 @@ struct RRResponse {
class BoundNetLog;
class RRResolverWorker;
class RRResolverJob;
-class RRResolverHandle;
// DnsRRResolver resolves arbitary DNS resource record types. It should not be
// confused with HostResolver and should not be used to resolve A/AAAA records.
@@ -117,11 +114,11 @@ class DnsRRResolver : public NonThreadSafe,
void HandleResult(const std::string& name, uint16 rrtype, int result,
const RRResponse& response);
- // cache maps from a request to a cached response. The cached answer may have
- // expired and the size of |cache| must be <= kMaxCacheEntries.
+ // cache_ maps from a request to a cached response. The cached answer may
+ // have expired and the size of |cache_| must be <= kMaxCacheEntries.
// < name , rrtype>
std::map<std::pair<std::string, uint16>, RRResponse> cache_;
- // inflight maps from a request to an active resolution which is taking
+ // inflight_ maps from a request to an active resolution which is taking
// place.
std::map<std::pair<std::string, uint16>, RRResolverJob*> inflight_;
@@ -136,4 +133,4 @@ class DnsRRResolver : public NonThreadSafe,
} // namespace net
-#endif // NET_BASE_DNSRR_RESOLVER_H_
+#endif // NET_BASE_DNSRR_RESOLVER_H_
diff --git a/net/base/escape.cc b/net/base/escape.cc
index 3c39f95..5479b82 100644
--- a/net/base/escape.cc
+++ b/net/base/escape.cc
@@ -71,19 +71,27 @@ const std::string Escape(const std::string& text, const Charmap& charmap,
//
// The basic rule is that we can't unescape anything that would changing parsing
// like # or ?. We also can't unescape &, =, or + since that could be part of a
-// query and that could change the server's parsing of the query.
+// query and that could change the server's parsing of the query. Nor can we
+// unescape \ since googleurl will convert it to a /.
+//
+// Lastly, we can't unescape anything that doesn't have a canonical
+// representation in a URL. This means that unescaping will change the URL, and
+// you could get different behavior if you copy and paste the URL, or press
+// enter in the URL bar. The list of characters that fall into this category
+// are the ones labeled PASS (allow either escaped or unescaped) in the big
+// lookup table at the top of googleurl/src/url_canon_path.cc
const char kUrlUnescape[128] = {
// NULL, control chars...
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// ' ' ! " # $ % & ' ( ) * + , - . /
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0,
// @ A B C D E F G H I J K L M N O
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// P Q R S T U V W X Y Z [ \ ] ^ _
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
// ` a b c d e f g h i j k l m n o
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// p q r s t u v w x y z { | } ~ <NBSP>
diff --git a/net/base/escape_unittest.cc b/net/base/escape_unittest.cc
index 01cd9e1..04a040e 100644
--- a/net/base/escape_unittest.cc
+++ b/net/base/escape_unittest.cc
@@ -159,17 +159,17 @@ TEST(EscapeTest, UnescapeURLComponentASCII) {
{"%%%%%%", UnescapeRule::NORMAL, "%%%%%%"},
{"Don't escape anything", UnescapeRule::NORMAL, "Don't escape anything"},
{"Invalid %escape %2", UnescapeRule::NORMAL, "Invalid %escape %2"},
- {"Some%20random text %25%3bOK", UnescapeRule::NONE,
- "Some%20random text %25%3bOK"},
- {"Some%20random text %25%3bOK", UnescapeRule::NORMAL,
- "Some%20random text %25;OK"},
- {"Some%20random text %25%3bOK", UnescapeRule::SPACES,
- "Some random text %25;OK"},
- {"Some%20random text %25%3bOK", UnescapeRule::URL_SPECIAL_CHARS,
- "Some%20random text %;OK"},
- {"Some%20random text %25%3bOK",
+ {"Some%20random text %25%2dOK", UnescapeRule::NONE,
+ "Some%20random text %25%2dOK"},
+ {"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
+ "Some%20random text %25-OK"},
+ {"Some%20random text %25%2dOK", UnescapeRule::SPACES,
+ "Some random text %25-OK"},
+ {"Some%20random text %25%2dOK", UnescapeRule::URL_SPECIAL_CHARS,
+ "Some%20random text %-OK"},
+ {"Some%20random text %25%2dOK",
UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
- "Some random text %;OK"},
+ "Some random text %-OK"},
{"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL, "\xA0\xB1\xC2\xD3\xE4\xF5"},
{"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL, "\xAa\xBb\xCc\xDd\xEe\xFf"},
// Certain URL-sensitive characters should not be unescaped unless asked.
@@ -220,17 +220,17 @@ TEST(EscapeTest, UnescapeURLComponent) {
{L"%%%%%%", UnescapeRule::NORMAL, L"%%%%%%"},
{L"Don't escape anything", UnescapeRule::NORMAL, L"Don't escape anything"},
{L"Invalid %escape %2", UnescapeRule::NORMAL, L"Invalid %escape %2"},
- {L"Some%20random text %25%3bOK", UnescapeRule::NONE,
- L"Some%20random text %25%3bOK"},
- {L"Some%20random text %25%3bOK", UnescapeRule::NORMAL,
- L"Some%20random text %25;OK"},
- {L"Some%20random text %25%3bOK", UnescapeRule::SPACES,
- L"Some random text %25;OK"},
- {L"Some%20random text %25%3bOK", UnescapeRule::URL_SPECIAL_CHARS,
- L"Some%20random text %;OK"},
- {L"Some%20random text %25%3bOK",
+ {L"Some%20random text %25%2dOK", UnescapeRule::NONE,
+ L"Some%20random text %25%2dOK"},
+ {L"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25-OK"},
+ {L"Some%20random text %25%2dOK", UnescapeRule::SPACES,
+ L"Some random text %25-OK"},
+ {L"Some%20random text %25%2dOK", UnescapeRule::URL_SPECIAL_CHARS,
+ L"Some%20random text %-OK"},
+ {L"Some%20random text %25%2dOK",
UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
- L"Some random text %;OK"},
+ L"Some random text %-OK"},
{L"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL, L"\xA0\xB1\xC2\xD3\xE4\xF5"},
{L"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL, L"\xAa\xBb\xCc\xDd\xEe\xFf"},
// Certain URL-sensitive characters should not be unescaped unless asked.
@@ -307,10 +307,10 @@ TEST(EscapeTest, UnescapeAndDecodeUTF8URLComponent) {
"+Invalid %escape %2+",
" Invalid %escape %2 ",
L"+Invalid %escape %2+"},
- { "Some random text %25%3BOK",
- "Some random text %25;OK",
- "Some random text %25;OK",
- L"Some random text %25;OK"},
+ { "Some random text %25%2dOK",
+ "Some random text %25-OK",
+ "Some random text %25-OK",
+ L"Some random text %25-OK"},
{ "%01%02%03%04%05%06%07%08%09",
"%01%02%03%04%05%06%07%08%09",
"%01%02%03%04%05%06%07%08%09",
@@ -349,9 +349,9 @@ TEST(EscapeTest, AdjustOffset) {
{"test", 2, 2},
{"test", 4, std::wstring::npos},
{"test", std::wstring::npos, std::wstring::npos},
- {"%3Btest", 6, 4},
- {"%3Btest", 2, std::wstring::npos},
- {"test%3B", 2, 2},
+ {"%2dtest", 6, 4},
+ {"%2dtest", 2, std::wstring::npos},
+ {"test%2d", 2, 2},
{"%E4%BD%A0+%E5%A5%BD", 9, 1},
{"%E4%BD%A0+%E5%A5%BD", 6, std::wstring::npos},
{"%ED%B0%80+%E5%A5%BD", 6, 6},
diff --git a/net/base/forwarding_net_log.cc b/net/base/forwarding_net_log.cc
deleted file mode 100644
index 7cfd6a9..0000000
--- a/net/base/forwarding_net_log.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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/base/forwarding_net_log.h"
-
-#include "base/lock.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-
-namespace net {
-
-// Reference-counted wrapper, so we can use PostThread and it can safely
-// outlive the parent ForwardingNetLog.
-class ForwardingNetLog::Core
- : public base::RefCountedThreadSafe<ForwardingNetLog::Core> {
- public:
- Core(NetLog* impl, MessageLoop* loop) : impl_(impl), loop_(loop) {
- DCHECK(impl);
- DCHECK(loop);
- }
-
- // Called once the parent ForwardingNetLog is being destroyed. It
- // is invalid to access |loop_| and |impl_| afterwards.
- void Orphan() {
- AutoLock l(lock_);
- loop_ = NULL;
- impl_ = NULL;
- }
-
- void AddEntry(EventType type,
- const base::TimeTicks& time,
- const Source& source,
- EventPhase phase,
- EventParameters* params) {
- AutoLock l(lock_);
- if (!loop_)
- return; // Was orphaned.
-
- loop_->PostTask(
- FROM_HERE,
- NewRunnableMethod(
- this, &Core::AddEntryOnLoop, type, time, source, phase,
- scoped_refptr<EventParameters>(params)));
- }
-
- private:
- void AddEntryOnLoop(EventType type,
- const base::TimeTicks& time,
- const Source& source,
- EventPhase phase,
- scoped_refptr<EventParameters> params) {
- AutoLock l(lock_);
- if (!loop_)
- return; // Was orphaned.
-
- DCHECK_EQ(MessageLoop::current(), loop_);
-
- impl_->AddEntry(type, time, source, phase, params);
- }
-
- Lock lock_;
- NetLog* impl_;
- MessageLoop* loop_;
-};
-
-ForwardingNetLog::ForwardingNetLog(NetLog* impl, MessageLoop* loop)
- : core_(new Core(impl, loop)) {
-}
-
-ForwardingNetLog::~ForwardingNetLog() {
- core_->Orphan();
-}
-
-void ForwardingNetLog::AddEntry(EventType type,
- const base::TimeTicks& time,
- const Source& source,
- EventPhase phase,
- EventParameters* params) {
- core_->AddEntry(type, time, source, phase, params);
-}
-
-uint32 ForwardingNetLog::NextID() {
- // Can't forward a synchronous API.
- CHECK(false) << "Not supported";
- return 0;
-}
-
-NetLog::LogLevel ForwardingNetLog::GetLogLevel() const {
- // Can't forward a synchronous API.
- CHECK(false) << "Not supported";
- return LOG_ALL_BUT_BYTES;
-}
-
-} // namespace net
-
diff --git a/net/base/forwarding_net_log.h b/net/base/forwarding_net_log.h
deleted file mode 100644
index 257b4c7..0000000
--- a/net/base/forwarding_net_log.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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_BASE_FORWARDING_NET_LOG_H_
-#define NET_BASE_FORWARDING_NET_LOG_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "net/base/net_log.h"
-
-class MessageLoop;
-
-namespace net {
-
-// ForwardingNetLog is a wrapper that can be called on any thread, and will
-// forward any calls to NetLog::AddEntry() over to |impl| on the specified
-// message loop.
-//
-// This allows using a non-threadsafe NetLog implementation from another
-// thread.
-//
-// TODO(eroman): Explore making NetLog threadsafe and obviating the need
-// for this class.
-class ForwardingNetLog : public NetLog {
- public:
- // Both |impl| and |loop| must outlive the lifetime of this instance.
- // |impl| will be operated only from |loop|.
- ForwardingNetLog(NetLog* impl, MessageLoop* loop);
-
- // On destruction any outstanding call to AddEntry() which didn't make
- // it to |loop| yet will be cancelled.
- ~ForwardingNetLog();
-
- // NetLog methods:
- virtual void AddEntry(EventType type,
- const base::TimeTicks& time,
- const Source& source,
- EventPhase phase,
- EventParameters* params);
- virtual uint32 NextID();
- virtual LogLevel GetLogLevel() const;
-
- private:
- class Core;
- scoped_refptr<Core> core_;
-
- DISALLOW_COPY_AND_ASSIGN(ForwardingNetLog);
-};
-
-} // namespace net
-
-#endif // NET_BASE_FORWARDING_NET_LOG_H_
-
diff --git a/net/base/forwarding_net_log_unittest.cc b/net/base/forwarding_net_log_unittest.cc
deleted file mode 100644
index 3f25129..0000000
--- a/net/base/forwarding_net_log_unittest.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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/base/forwarding_net_log.h"
-
-#include "base/message_loop.h"
-#include "net/base/capturing_net_log.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace {
-
-// Test forwarding a call to AddEntry() to another implementation, operating
-// on this same message loop.
-TEST(ForwardingNetLogTest, Basic) {
- // Create a forwarding NetLog that sends messages to this same thread.
- CapturingNetLog log(CapturingNetLog::kUnbounded);
- ForwardingNetLog forwarding(&log, MessageLoop::current());
-
- EXPECT_EQ(0u, log.entries().size());
-
- NetLogStringParameter* params = new NetLogStringParameter("xxx", "yyy");
-
- forwarding.AddEntry(
- NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
- base::TimeTicks(),
- NetLog::Source(),
- NetLog::PHASE_NONE,
- params);
-
- // Should still be empty, since we posted an async task.
- EXPECT_EQ(0u, log.entries().size());
-
- MessageLoop::current()->RunAllPending();
-
- // After draining the message loop, we should now have executed the task
- // and hence emitted the log entry.
- ASSERT_EQ(1u, log.entries().size());
-
- // Check that the forwarded call contained received all the right inputs.
- EXPECT_EQ(NetLog::TYPE_PAC_JAVASCRIPT_ALERT, log.entries()[0].type);
- EXPECT_EQ(NetLog::SOURCE_NONE, log.entries()[0].source.type);
- EXPECT_EQ(NetLog::PHASE_NONE, log.entries()[0].phase);
- EXPECT_EQ(params, log.entries()[0].extra_parameters.get());
-
- // Check that the parameters is still referenced. (if the reference was
- // lost then this will be a memory error and probaby crash).
- EXPECT_EQ("yyy", params->value());
-}
-
-// Test forwarding a call to AddEntry() to another implementation that runs
-// on the same message loop. However destroy the forwarder before the posted
-// task has a chance to run.
-TEST(ForwardingNetLogTest, Orphan) {
- // Create a forwarding NetLog that sends messages to this same thread.
- CapturingNetLog log(CapturingNetLog::kUnbounded);
- {
- ForwardingNetLog forwarding(&log, MessageLoop::current());
- EXPECT_EQ(0u, log.entries().size());
-
- forwarding.AddEntry(
- NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
- base::TimeTicks(),
- NetLog::Source(),
- NetLog::PHASE_NONE,
- NULL);
-
- // Should still be empty, since we posted an async task.
- EXPECT_EQ(0u, log.entries().size());
- }
-
- // At this point the ForwardingNetLog is deleted. However it had already
- // posted a task to the message loop. Once we drain the message loop, we
- // verify that the task didn't actually try to emit to the NetLog.
- MessageLoop::current()->RunAllPending();
- EXPECT_EQ(0u, log.entries().size());
-}
-
-} // namespace
-
-} // namespace net
-
diff --git a/net/base/host_resolver.cc b/net/base/host_resolver.cc
index fbd63bd..a8b642a 100644
--- a/net/base/host_resolver.cc
+++ b/net/base/host_resolver.cc
@@ -25,6 +25,14 @@ HostResolver::HostResolver() {
HostResolver::~HostResolver() {
}
+AddressFamily HostResolver::GetDefaultAddressFamily() const {
+ return net::ADDRESS_FAMILY_UNSPECIFIED;
+}
+
+HostResolverImpl* HostResolver::GetAsHostResolverImpl() {
+ return NULL;
+}
+
SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver)
: resolver_(resolver),
cur_request_(NULL),
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h
index 471ad8a..4fc5c89 100644
--- a/net/base/host_resolver.h
+++ b/net/base/host_resolver.h
@@ -170,14 +170,12 @@ class HostResolver {
// results to AF_INET by passing in ADDRESS_FAMILY_IPV4, or to
// AF_INET6 by passing in ADDRESS_FAMILY_IPV6.
virtual void SetDefaultAddressFamily(AddressFamily address_family) {}
- virtual AddressFamily GetDefaultAddressFamily() const {
- return net::ADDRESS_FAMILY_UNSPECIFIED;
- }
+ virtual AddressFamily GetDefaultAddressFamily() const;
// Returns |this| cast to a HostResolverImpl*, or NULL if the subclass
// is not compatible with HostResolverImpl. Used primarily to expose
// additional functionality on the about:net-internals page.
- virtual HostResolverImpl* GetAsHostResolverImpl() { return NULL; }
+ virtual HostResolverImpl* GetAsHostResolverImpl();
// Does additional cleanup prior to destruction.
virtual void Shutdown() {}
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc
index 3dd99c4..fded5ff 100644
--- a/net/base/host_resolver_impl.cc
+++ b/net/base/host_resolver_impl.cc
@@ -1135,6 +1135,10 @@ void HostResolverImpl::ProbeIPv6Support() {
OnIPAddressChanged(); // Give initial setup call.
}
+HostResolverImpl* HostResolverImpl::GetAsHostResolverImpl() {
+ return this;
+}
+
void HostResolverImpl::Shutdown() {
DCHECK(CalledOnValidThread());
diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h
index 46ce31d..68c8c0b 100644
--- a/net/base/host_resolver_impl.h
+++ b/net/base/host_resolver_impl.h
@@ -105,7 +105,7 @@ class HostResolverImpl : public HostResolver,
// address family to IPv4 iff IPv6 is not supported.
void ProbeIPv6Support();
- virtual HostResolverImpl* GetAsHostResolverImpl() { return this; }
+ virtual HostResolverImpl* GetAsHostResolverImpl();
// TODO(eroman): hack for http://crbug.com/15513
virtual void Shutdown();
diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc
index f3bdb74..4d26ab9 100644
--- a/net/base/host_resolver_impl_unittest.cc
+++ b/net/base/host_resolver_impl_unittest.cc
@@ -271,11 +271,14 @@ TEST_F(HostResolverImplTest, SynchronousLookup) {
int err = host_resolver->Resolve(info, &addrlist, NULL, NULL, log.bound());
EXPECT_EQ(OK, err);
- EXPECT_EQ(2u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(2u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
const struct addrinfo* ainfo = addrlist.head();
EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next);
@@ -304,18 +307,23 @@ TEST_F(HostResolverImplTest, AsynchronousLookup) {
log.bound());
EXPECT_EQ(ERR_IO_PENDING, err);
- EXPECT_EQ(1u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(1u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
MessageLoop::current()->Run();
ASSERT_TRUE(callback_called_);
ASSERT_EQ(OK, callback_result_);
- EXPECT_EQ(2u, log.entries().size());
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(2u, entries.size());
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
const struct addrinfo* ainfo = addrlist.head();
EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next);
@@ -356,31 +364,37 @@ TEST_F(HostResolverImplTest, CanceledAsynchronousLookup) {
resolver_proc->Signal();
- EXPECT_EQ(2u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(2u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
+
+ net::CapturingNetLog::EntryList net_log_entries;
+ net_log.GetEntries(&net_log_entries);
- int pos = net::ExpectLogContainsSomewhereAfter(net_log.entries(), 0,
+ int pos = net::ExpectLogContainsSomewhereAfter(net_log_entries, 0,
net::NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST,
net::NetLog::PHASE_BEGIN);
- pos = net::ExpectLogContainsSomewhereAfter(net_log.entries(), pos + 1,
+ pos = net::ExpectLogContainsSomewhereAfter(net_log_entries, pos + 1,
net::NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
net::NetLog::PHASE_BEGIN);
// Both Job and Request need to be cancelled.
- pos = net::ExpectLogContainsSomewhereAfter(net_log.entries(), pos + 1,
+ pos = net::ExpectLogContainsSomewhereAfter(net_log_entries, pos + 1,
net::NetLog::TYPE_CANCELLED,
net::NetLog::PHASE_NONE);
// Don't care about order in which they end, or when the other one is
// cancelled.
- net::ExpectLogContainsSomewhereAfter(net_log.entries(), pos + 1,
+ net::ExpectLogContainsSomewhereAfter(net_log_entries, pos + 1,
net::NetLog::TYPE_CANCELLED,
net::NetLog::PHASE_NONE);
- net::ExpectLogContainsSomewhereAfter(net_log.entries(), pos + 1,
+ net::ExpectLogContainsSomewhereAfter(net_log_entries, pos + 1,
net::NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST,
net::NetLog::PHASE_END);
- net::ExpectLogContainsSomewhereAfter(net_log.entries(), pos + 1,
+ net::ExpectLogContainsSomewhereAfter(net_log_entries, pos + 1,
net::NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
net::NetLog::PHASE_END);
@@ -943,11 +957,14 @@ TEST_F(HostResolverImplTest, Observers) {
int rv = host_resolver->Resolve(info1, &addrlist, NULL, NULL, log.bound());
EXPECT_EQ(OK, rv);
- EXPECT_EQ(2u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(2u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 0, NetLog::TYPE_HOST_RESOLVER_IMPL));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
+ entries, 1, NetLog::TYPE_HOST_RESOLVER_IMPL));
EXPECT_EQ(1U, observer.start_log.size());
EXPECT_EQ(1U, observer.finish_log.size());
diff --git a/net/base/keygen_handler_openssl.cc b/net/base/keygen_handler_openssl.cc
index 0f5d874..73aabd7 100644
--- a/net/base/keygen_handler_openssl.cc
+++ b/net/base/keygen_handler_openssl.cc
@@ -4,15 +4,39 @@
#include "net/base/keygen_handler.h"
-#if defined(USE_OPENSSL)
+#include <openssl/ssl.h>
+
+#include "base/crypto/rsa_private_key.h"
+#include "base/logging.h"
+#include "base/openssl_util.h"
+#include "base/scoped_ptr.h"
+#include "net/base/openssl_private_key_store.h"
namespace net {
std::string KeygenHandler::GenKeyAndSignChallenge() {
- // TODO(bulach): implement me.
- return "";
+ scoped_ptr<base::RSAPrivateKey> key(
+ base::RSAPrivateKey::Create(key_size_in_bits_));
+ EVP_PKEY* pkey = key->key();
+
+ if (stores_key_)
+ OpenSSLPrivateKeyStore::GetInstance()->StorePrivateKey(url_, pkey);
+
+ base::ScopedOpenSSL<NETSCAPE_SPKI, NETSCAPE_SPKI_free> spki(
+ NETSCAPE_SPKI_new());
+ ASN1_STRING_set(spki.get()->spkac->challenge,
+ challenge_.data(), challenge_.size());
+ NETSCAPE_SPKI_set_pubkey(spki.get(), pkey);
+ // Using MD5 as this is what is required in HTML5, even though the SPKI
+ // structure does allow the use of a SHA-1 signature.
+ NETSCAPE_SPKI_sign(spki.get(), pkey, EVP_md5());
+ char* spkistr = NETSCAPE_SPKI_b64_encode(spki.get());
+
+ std::string result(spkistr);
+ OPENSSL_free(spkistr);
+
+ return result;
}
} // namespace net
-#endif // USE_OPENSSL
diff --git a/net/base/keygen_handler_unittest.cc b/net/base/keygen_handler_unittest.cc
index d3bf4f5..f4251f2 100644
--- a/net/base/keygen_handler_unittest.cc
+++ b/net/base/keygen_handler_unittest.cc
@@ -4,14 +4,9 @@
#include "net/base/keygen_handler.h"
-#include "build/build_config.h" // Needs to be imported early for USE_NSS
-
-#if defined(USE_NSS)
-#include <private/pprthred.h> // PR_DetachThread
-#endif
-
#include <string>
+#include "build/build_config.h"
#include "base/base64.h"
#include "base/logging.h"
#include "base/nss_util.h"
@@ -21,6 +16,10 @@
#include "base/worker_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(USE_NSS)
+#include <private/pprthred.h> // PR_DetachThread
+#endif
+
namespace net {
namespace {
@@ -96,7 +95,7 @@ class ConcurrencyTestTask : public Task {
base::ThreadRestrictions::ScopedAllowSingleton scoped_allow_singleton;
KeygenHandler handler(768, "some challenge",
GURL("http://www.example.com"));
- handler.set_stores_key(false); // Don't leave the key-pair behind.
+ handler.set_stores_key(false); // Don't leave the key-pair behind.
*result_ = handler.GenKeyAndSignChallenge();
event_->Signal();
#if defined(USE_NSS)
diff --git a/net/base/listen_socket.h b/net/base/listen_socket.h
index 7ce8887..e730b82 100644
--- a/net/base/listen_socket.h
+++ b/net/base/listen_socket.h
@@ -114,8 +114,8 @@ class ListenSocket : public base::RefCountedThreadSafe<ListenSocket>,
// The socket's libevent wrapper
MessageLoopForIO::FileDescriptorWatcher watcher_;
// Called by MessagePumpLibevent when the socket is ready to do I/O
- void OnFileCanReadWithoutBlocking(int fd);
- void OnFileCanWriteWithoutBlocking(int fd);
+ virtual void OnFileCanReadWithoutBlocking(int fd);
+ virtual void OnFileCanWriteWithoutBlocking(int fd);
#endif
SOCKET socket_;
diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h
index 6f230bb..a8420a5 100644
--- a/net/base/load_flags_list.h
+++ b/net/base/load_flags_list.h
@@ -30,7 +30,7 @@ LOAD_FLAG(ONLY_FROM_CACHE, 1 << 3)
LOAD_FLAG(DISABLE_CACHE, 1 << 4)
// This is a navigation that will not be intercepted by any registered
-// URLRequest::Interceptors.
+// net::URLRequest::Interceptors.
LOAD_FLAG(DISABLE_INTERCEPT, 1 << 5)
// If present, upload progress messages should be provided to initiator.
diff --git a/net/base/load_states.h b/net/base/load_states.h
index d80e182..64b2a46 100644
--- a/net/base/load_states.h
+++ b/net/base/load_states.h
@@ -13,7 +13,7 @@ namespace net {
enum LoadState {
// This is the default state. It corresponds to a resource load that has
// either not yet begun or is idle waiting for the consumer to do something
- // to move things along (e.g., the consumer of an URLRequest may not have
+ // to move things along (e.g., the consumer of an net::URLRequest may not have
// called Read yet).
LOAD_STATE_IDLE,
@@ -65,7 +65,7 @@ enum LoadState {
// read to complete. In the case of a HTTP transaction, this corresponds to
// the period after the response headers have been received and before all of
// the response body has been downloaded. (NOTE: This state only applies for
- // an URLRequest while there is an outstanding Read operation.)
+ // an net::URLRequest while there is an outstanding Read operation.)
LOAD_STATE_READING_RESPONSE,
};
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index bd16462..1a52b99 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 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.
@@ -146,8 +146,6 @@ static const MagicNumber kMagicNumbers[] = {
MAGIC_NUMBER("image/tiff", "II*")
MAGIC_NUMBER("image/tiff", "MM\x00*")
MAGIC_NUMBER("audio/mpeg", "ID3")
- MAGIC_NUMBER("image/webp", "RIFF....WEBPVP8 ")
- MAGIC_NUMBER("video/webm", "\x1A\x45\xDF\xA3")
// TODO(abarth): we don't handle partial byte matches yet
// MAGIC_NUMBER("video/mpeg", "\x00\x00\x01\xB")
// MAGIC_NUMBER("audio/mpeg", "\xFF\xE")
@@ -217,19 +215,6 @@ static scoped_refptr<base::Histogram> UMASnifferHistogramGet(const char* name,
return counter;
}
-// Compare content header to a magic number where magic_entry can contain '.'
-// for single character of anything, allowing some bytes to be skipped.
-static bool MagicCmp(const char* magic_entry, const char* content, size_t len) {
- while (len) {
- if ((*magic_entry != '.') && (*magic_entry != *content))
- return false;
- ++magic_entry;
- ++content;
- --len;
- }
- return true;
-}
-
static bool MatchMagicNumber(const char* content, size_t size,
const MagicNumber* magic_entry,
std::string* result) {
@@ -254,7 +239,7 @@ static bool MatchMagicNumber(const char* content, size_t size,
}
} else {
if (size >= len)
- match = MagicCmp(magic_entry->magic, content, len);
+ match = (memcmp(magic_entry->magic, content, len) == 0);
}
if (match) {
@@ -266,8 +251,7 @@ static bool MatchMagicNumber(const char* content, size_t size,
static bool CheckForMagicNumbers(const char* content, size_t size,
const MagicNumber* magic, size_t magic_len,
- base::Histogram* counter,
- std::string* result) {
+ base::Histogram* counter, std::string* result) {
for (size_t i = 0; i < magic_len; ++i) {
if (MatchMagicNumber(content, size, &(magic[i]), result)) {
if (counter) counter->Add(static_cast<int>(i));
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index ddcfc4b..d95c029 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -9,8 +9,8 @@
#include "net/base/platform_mime_util.h"
#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/singleton.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
@@ -51,7 +51,7 @@ class MimeUtil : public PlatformMimeUtil {
const std::vector<std::string>& codecs) const;
private:
- friend struct DefaultSingletonTraits<MimeUtil>;
+ friend struct base::DefaultLazyInstanceTraits<MimeUtil>;
MimeUtil() {
InitializeMimeTypeMaps();
}
@@ -71,6 +71,8 @@ class MimeUtil : public PlatformMimeUtil {
StrictMappings strict_format_map_;
}; // class MimeUtil
+static base::LazyInstance<MimeUtil> g_mime_util(base::LINKER_INITIALIZED);
+
struct MimeInfo {
const char* mime_type;
const char* extensions; // comma separated list
@@ -473,70 +475,67 @@ bool MimeUtil::IsSupportedStrictMediaMimeType(const std::string& mime_type,
// Wrappers for the singleton
//----------------------------------------------------------------------------
-static MimeUtil* GetMimeUtil() {
- return Singleton<MimeUtil>::get();
-}
-
bool GetMimeTypeFromExtension(const FilePath::StringType& ext,
std::string* mime_type) {
- return GetMimeUtil()->GetMimeTypeFromExtension(ext, mime_type);
+ return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type);
}
bool GetMimeTypeFromFile(const FilePath& file_path, std::string* mime_type) {
- return GetMimeUtil()->GetMimeTypeFromFile(file_path, mime_type);
+ return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type);
}
bool GetPreferredExtensionForMimeType(const std::string& mime_type,
FilePath::StringType* extension) {
- return GetMimeUtil()->GetPreferredExtensionForMimeType(mime_type, extension);
+ return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type,
+ extension);
}
bool IsSupportedImageMimeType(const char* mime_type) {
- return GetMimeUtil()->IsSupportedImageMimeType(mime_type);
+ return g_mime_util.Get().IsSupportedImageMimeType(mime_type);
}
bool IsSupportedMediaMimeType(const char* mime_type) {
- return GetMimeUtil()->IsSupportedMediaMimeType(mime_type);
+ return g_mime_util.Get().IsSupportedMediaMimeType(mime_type);
}
bool IsSupportedNonImageMimeType(const char* mime_type) {
- return GetMimeUtil()->IsSupportedNonImageMimeType(mime_type);
+ return g_mime_util.Get().IsSupportedNonImageMimeType(mime_type);
}
bool IsSupportedJavascriptMimeType(const char* mime_type) {
- return GetMimeUtil()->IsSupportedJavascriptMimeType(mime_type);
+ return g_mime_util.Get().IsSupportedJavascriptMimeType(mime_type);
}
bool IsViewSourceMimeType(const char* mime_type) {
- return GetMimeUtil()->IsViewSourceMimeType(mime_type);
+ return g_mime_util.Get().IsViewSourceMimeType(mime_type);
}
bool IsSupportedMimeType(const std::string& mime_type) {
- return GetMimeUtil()->IsSupportedMimeType(mime_type);
+ return g_mime_util.Get().IsSupportedMimeType(mime_type);
}
bool MatchesMimeType(const std::string &mime_type_pattern,
const std::string &mime_type) {
- return GetMimeUtil()->MatchesMimeType(mime_type_pattern, mime_type);
+ return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type);
}
bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) {
- return GetMimeUtil()->AreSupportedMediaCodecs(codecs);
+ return g_mime_util.Get().AreSupportedMediaCodecs(codecs);
}
bool IsStrictMediaMimeType(const std::string& mime_type) {
- return GetMimeUtil()->IsStrictMediaMimeType(mime_type);
+ return g_mime_util.Get().IsStrictMediaMimeType(mime_type);
}
bool IsSupportedStrictMediaMimeType(const std::string& mime_type,
const std::vector<std::string>& codecs) {
- return GetMimeUtil()->IsSupportedStrictMediaMimeType(mime_type, codecs);
+ return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs);
}
void ParseCodecString(const std::string& codecs,
std::vector<std::string>* codecs_out,
const bool strip) {
- GetMimeUtil()->ParseCodecString(codecs, codecs_out, strip);
+ g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip);
}
namespace {
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index bc7065d..8f94c4a 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -215,6 +215,11 @@ NET_ERROR(NETWORK_ACCESS_DENIED, -138)
// The request throttler module cancelled this request to avoid DDOS.
NET_ERROR(TEMPORARILY_THROTTLED, -139)
+// A request to create an SSL tunnel connection through the HTTPS proxy
+// received a non-200 (OK) and non-407 (Proxy Auth) response. The response
+// body might include a description of why the request failed.
+NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE, -140)
+
// Certificate error codes
//
// The values of certificate error codes must be consecutive.
diff --git a/net/base/net_log.cc b/net/base/net_log.cc
index 1499d72..c9e7319 100644
--- a/net/base/net_log.cc
+++ b/net/base/net_log.cc
@@ -194,4 +194,27 @@ Value* NetLogSourceParameter::ToValue() const {
return dict;
}
+ScopedNetLogEvent::ScopedNetLogEvent(
+ const BoundNetLog& net_log,
+ NetLog::EventType event_type,
+ const scoped_refptr<NetLog::EventParameters>& params)
+ : net_log_(net_log),
+ event_type_(event_type) {
+ net_log_.BeginEvent(event_type, params);
+}
+
+ScopedNetLogEvent::~ScopedNetLogEvent() {
+ net_log_.EndEvent(event_type_, end_event_params_);
+}
+
+void ScopedNetLogEvent::SetEndEventParameters(
+ const scoped_refptr<NetLog::EventParameters>& end_event_params) {
+ DCHECK(!end_event_params_.get());
+ end_event_params_ = end_event_params;
+}
+
+const BoundNetLog& ScopedNetLogEvent::net_log() const {
+ return net_log_;
+}
+
} // namespace net
diff --git a/net/base/net_log.h b/net/base/net_log.h
index ad775fa..b8f903d 100644
--- a/net/base/net_log.h
+++ b/net/base/net_log.h
@@ -22,20 +22,17 @@ namespace net {
// NetLog is the destination for log messages generated by the network stack.
// Each log message has a "source" field which identifies the specific entity
-// that generated the message (for example, which URLRequest or which
+// that generated the message (for example, which net::URLRequest or which
// SocketStream).
//
// To avoid needing to pass in the "source id" to the logging functions, NetLog
// is usually accessed through a BoundNetLog, which will always pass in a
// specific source ID.
//
-// Note that NetLog is NOT THREADSAFE.
-//
// ******** The NetLog (and associated logging) is a work in progress ********
//
// TODO(eroman): Remove the 'const' qualitifer from the BoundNetLog methods.
-// TODO(eroman): Make the DNS jobs emit into the NetLog.
-// TODO(eroman): Start a new Source each time URLRequest redirects
+// TODO(eroman): Start a new Source each time net::URLRequest redirects
// (simpler to reason about each as a separate entity).
class NetLog {
@@ -273,6 +270,30 @@ class NetLogSourceParameter : public NetLog::EventParameters {
const NetLog::Source value_;
};
+// ScopedNetLogEvent logs a begin event on creation, and the corresponding end
+// event on destruction.
+class ScopedNetLogEvent {
+ public:
+ ScopedNetLogEvent(const BoundNetLog& net_log,
+ NetLog::EventType event_type,
+ const scoped_refptr<NetLog::EventParameters>& params);
+
+ ~ScopedNetLogEvent();
+
+ // Sets the parameters that will logged on object destruction. Can be called
+ // at most once for a given ScopedNetLogEvent object. If not called, the end
+ // event will have no parameters.
+ void SetEndEventParameters(
+ const scoped_refptr<NetLog::EventParameters>& end_event_params);
+
+ const BoundNetLog& net_log() const;
+
+ private:
+ BoundNetLog net_log_;
+ const NetLog::EventType event_type_;
+ scoped_refptr<NetLog::EventParameters> end_event_params_;
+};
+
} // namespace net
#endif // NET_BASE_NET_LOG_H_
diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h
index 0021c0d..f1bc4f8 100644
--- a/net/base/net_log_event_type_list.h
+++ b/net/base/net_log_event_type_list.h
@@ -13,7 +13,8 @@
// log context around it.)
EVENT_TYPE(CANCELLED)
-// Marks the creation/destruction of a request (URLRequest or SocketStream).
+// Marks the creation/destruction of a request (net::URLRequest or
+// SocketStream).
EVENT_TYPE(REQUEST_ALIVE)
// ------------------------------------------------------------------------
@@ -324,6 +325,9 @@ EVENT_TYPE(SOCKS_UNKNOWN_ADDRESS_TYPE)
// The start/end of a SSL connect().
EVENT_TYPE(SSL_CONNECT)
+// The start/end of a SSL accept().
+EVENT_TYPE(SSL_ACCEPT)
+
// An SSL error occurred while trying to do the indicated activity.
// The following parameters are attached to the event:
// {
@@ -464,12 +468,12 @@ EVENT_TYPE(SOCKET_POOL_BOUND_TO_SOCKET)
EVENT_TYPE(SOCKET_POOL_CONNECTING_N_SOCKETS)
// ------------------------------------------------------------------------
-// URLRequest
+// net::URLRequest
// ------------------------------------------------------------------------
-// Measures the time it took a URLRequestJob to start. For the most part this
-// corresponds with the time between URLRequest::Start() and
-// URLRequest::ResponseStarted(), however it is also repeated for every
+// Measures the time it took a net::URLRequestJob to start. For the most part
+// this corresponds with the time between net::URLRequest::Start() and
+// net::URLRequest::ResponseStarted(), however it is also repeated for every
// redirect, and every intercepted job that handles the request.
//
// For the BEGIN phase, the following parameters are attached:
@@ -486,7 +490,7 @@ EVENT_TYPE(SOCKET_POOL_CONNECTING_N_SOCKETS)
// }
EVENT_TYPE(URL_REQUEST_START_JOB)
-// This event is sent once a URLRequest receives a redirect. The parameters
+// This event is sent once a net::URLRequest receives a redirect. The parameters
// attached to the event are:
// {
// "location": <The URL that was redirected to>
@@ -589,7 +593,7 @@ EVENT_TYPE(SPDY_SESSION)
EVENT_TYPE(SPDY_SESSION_SYN_STREAM)
// This event is sent for a SPDY SYN_STREAM pushed by the server, where a
-// URLRequest is already waiting for the stream.
+// net::URLRequest is already waiting for the stream.
// The following parameters are attached:
// {
// "flags": <The control frame flags>
diff --git a/net/base/net_log_unittest.cc b/net/base/net_log_unittest.cc
new file mode 100644
index 0000000..8523955
--- /dev/null
+++ b/net/base/net_log_unittest.cc
@@ -0,0 +1,34 @@
+// 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/base/capturing_net_log.h"
+#include "net/base/net_log.h"
+#include "net/base/net_log_unittest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+TEST(NetLog, ScopedNetLogEventTest) {
+ CapturingNetLog log(CapturingNetLog::kUnbounded);
+ BoundNetLog net_log(BoundNetLog::Make(&log, NetLog::SOURCE_URL_REQUEST));
+
+ scoped_ptr<ScopedNetLogEvent> net_log_event(
+ new ScopedNetLogEvent(net_log, NetLog::TYPE_REQUEST_ALIVE, NULL));
+
+ CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+ EXPECT_EQ(1u, entries.size());
+ EXPECT_TRUE(LogContainsBeginEvent(entries, 0, NetLog::TYPE_REQUEST_ALIVE));
+
+ net_log_event.reset();
+ log.GetEntries(&entries);
+ EXPECT_EQ(2u, entries.size());
+ EXPECT_TRUE(LogContainsEndEvent(entries, 1, NetLog::TYPE_REQUEST_ALIVE));
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/base/net_util.cc b/net/base/net_util.cc
index 5e02544..1562951 100644
--- a/net/base/net_util.cc
+++ b/net/base/net_util.cc
@@ -518,6 +518,11 @@ bool IsCompatibleWithASCIILetters(const std::string& lang) {
typedef std::map<std::string, icu::UnicodeSet*> LangToExemplarSetMap;
class LangToExemplarSet {
+ public:
+ static LangToExemplarSet* GetInstance() {
+ return Singleton<LangToExemplarSet>::get();
+ }
+
private:
LangToExemplarSetMap map;
LangToExemplarSet() { }
@@ -535,7 +540,7 @@ class LangToExemplarSet {
bool GetExemplarSetForLang(const std::string& lang,
icu::UnicodeSet** lang_set) {
- const LangToExemplarSetMap& map = Singleton<LangToExemplarSet>()->map;
+ const LangToExemplarSetMap& map = LangToExemplarSet::GetInstance()->map;
LangToExemplarSetMap::const_iterator pos = map.find(lang);
if (pos != map.end()) {
*lang_set = pos->second;
@@ -546,7 +551,7 @@ bool GetExemplarSetForLang(const std::string& lang,
void SetExemplarSetForLang(const std::string& lang,
icu::UnicodeSet* lang_set) {
- LangToExemplarSetMap& map = Singleton<LangToExemplarSet>()->map;
+ LangToExemplarSetMap& map = LangToExemplarSet::GetInstance()->map;
map.insert(std::make_pair(lang, lang_set));
}
@@ -1052,7 +1057,7 @@ const FormatUrlType kFormatUrlOmitAll = kFormatUrlOmitUsernamePassword |
kFormatUrlOmitHTTP | kFormatUrlOmitTrailingSlashOnBareHostname;
// TODO(viettrungluu): We don't want non-POD globals; change this.
-std::set<int> explicitly_allowed_ports;
+std::multiset<int> explicitly_allowed_ports;
GURL FilePathToFileURL(const FilePath& path) {
// Produce a URL like "file:///C:/foo" for a regular file, or
@@ -1145,7 +1150,9 @@ std::string GetFileNameFromCD(const std::string& header,
// RFC 5987 value should be ASCII-only.
if (!IsStringASCII(value))
return std::string();
- std::string tmp = UnescapeURLComponent(value, UnescapeRule::SPACES);
+ std::string tmp = UnescapeURLComponent(
+ value,
+ UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
if (base::ConvertToUtf8AndNormalize(tmp, charset, &decoded))
return decoded;
}
@@ -1360,7 +1367,7 @@ std::string GetDirectoryListingEntry(const string16& name,
string16 modified_str;
// |modified| can be NULL in FTP listings.
if (!modified.is_null()) {
- modified_str = WideToUTF16Hack(base::TimeFormatShortDateAndTime(modified));
+ modified_str = base::TimeFormatShortDateAndTime(modified);
}
base::JsonDoubleQuote(modified_str, true, &result);
@@ -1494,12 +1501,7 @@ bool IsPortAllowedByOverride(int port) {
if (explicitly_allowed_ports.empty())
return false;
- std::set<int>::const_iterator it =
- std::find(explicitly_allowed_ports.begin(),
- explicitly_allowed_ports.end(),
- port);
-
- return it != explicitly_allowed_ports.end();
+ return explicitly_allowed_ports.count(port) > 0;
}
int SetNonBlocking(int fd) {
@@ -1724,7 +1726,7 @@ void SetExplicitlyAllowedPorts(const std::string& allowed_ports) {
if (allowed_ports.empty())
return;
- std::set<int> ports;
+ std::multiset<int> ports;
size_t last = 0;
size_t size = allowed_ports.size();
// The comma delimiter.
@@ -1750,6 +1752,18 @@ void SetExplicitlyAllowedPorts(const std::string& allowed_ports) {
explicitly_allowed_ports = ports;
}
+ScopedPortException::ScopedPortException(int port) : port_(port) {
+ explicitly_allowed_ports.insert(port);
+}
+
+ScopedPortException::~ScopedPortException() {
+ std::multiset<int>::iterator it = explicitly_allowed_ports.find(port_);
+ if (it != explicitly_allowed_ports.end())
+ explicitly_allowed_ports.erase(it);
+ else
+ NOTREACHED();
+}
+
enum IPv6SupportStatus {
IPV6_CANNOT_CREATE_SOCKETS,
IPV6_CAN_CREATE_SOCKETS,
diff --git a/net/base/net_util.h b/net/base/net_util.h
index 4b87c70..bb145e0 100644
--- a/net/base/net_util.h
+++ b/net/base/net_util.h
@@ -71,7 +71,7 @@ extern const FormatUrlType kFormatUrlOmitTrailingSlashOnBareHostname;
extern const FormatUrlType kFormatUrlOmitAll;
// Holds a list of ports that should be accepted despite bans.
-extern std::set<int> explicitly_allowed_ports;
+extern std::multiset<int> explicitly_allowed_ports;
// Given the full path to a file name, creates a file: URL. The returned URL
// may not be valid if the input is malformed.
@@ -125,7 +125,7 @@ void GetIdentityFromURL(const GURL& url,
std::string GetHostOrSpecFromURL(const GURL& url);
// Return the value of the HTTP response header with name 'name'. 'headers'
-// should be in the format that URLRequest::GetResponseHeaders() returns.
+// should be in the format that net::URLRequest::GetResponseHeaders() returns.
// Returns the empty string if the header is not found.
std::wstring GetSpecificHeader(const std::wstring& headers,
const std::wstring& name);
@@ -338,6 +338,17 @@ GURL SimplifyUrlForRequest(const GURL& url);
void SetExplicitlyAllowedPorts(const std::string& allowed_ports);
+class ScopedPortException {
+ public:
+ ScopedPortException(int port);
+ ~ScopedPortException();
+
+ private:
+ int port_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedPortException);
+};
+
// Perform a simplistic test to see if IPv6 is supported by trying to create an
// IPv6 socket.
// TODO(jar): Make test more in-depth as needed.
diff --git a/net/base/openssl_memory_private_key_store.cc b/net/base/openssl_memory_private_key_store.cc
new file mode 100644
index 0000000..6b65dbe
--- /dev/null
+++ b/net/base/openssl_memory_private_key_store.cc
@@ -0,0 +1,68 @@
+// 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.
+
+// Defines an in-memory private key store, primarily used for testing.
+
+#include <openssl/evp.h>
+
+#include "net/base/openssl_private_key_store.h"
+
+#include "base/logging.h"
+#include "base/openssl_util.h"
+#include "base/singleton.h"
+#include "net/base/x509_certificate.h"
+
+namespace net {
+
+namespace {
+
+class OpenSSLMemoryKeyStore : public OpenSSLPrivateKeyStore {
+ public:
+ OpenSSLMemoryKeyStore() {}
+
+ static OpenSSLMemoryKeyStore* GetInstance() {
+ return Singleton<OpenSSLMemoryKeyStore>::get();
+ }
+
+ virtual ~OpenSSLMemoryKeyStore() {
+ AutoLock lock(lock_);
+ for (std::vector<EVP_PKEY*>::iterator it = keys_.begin();
+ it != keys_.end(); ++it) {
+ EVP_PKEY_free(*it);
+ }
+ }
+
+ virtual bool StorePrivateKey(const GURL& url, EVP_PKEY* pkey) {
+ CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+ AutoLock lock(lock_);
+ keys_.push_back(pkey);
+ return true;
+ }
+
+ virtual EVP_PKEY* FetchPrivateKey(EVP_PKEY* pkey) {
+ AutoLock lock(lock_);
+ for (std::vector<EVP_PKEY*>::iterator it = keys_.begin();
+ it != keys_.end(); ++it) {
+ if (EVP_PKEY_cmp(*it, pkey) == 1)
+ return *it;
+ }
+ return NULL;
+ }
+
+ private:
+ std::vector<EVP_PKEY*> keys_;
+ Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(OpenSSLMemoryKeyStore);
+};
+
+} // namespace
+
+// static
+OpenSSLPrivateKeyStore* OpenSSLPrivateKeyStore::GetInstance() {
+ return OpenSSLMemoryKeyStore::GetInstance();
+}
+
+} // namespace net
+
diff --git a/net/base/openssl_private_key_store.h b/net/base/openssl_private_key_store.h
new file mode 100644
index 0000000..17f8fe1
--- /dev/null
+++ b/net/base/openssl_private_key_store.h
@@ -0,0 +1,51 @@
+// 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_BASE_OPENSSL_PRIVATE_KEY_STORE_H_
+#define NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+typedef struct evp_pkey_st EVP_PKEY;
+
+class GURL;
+
+namespace net {
+
+// Defines an abstract store for private keys; the OpenSSL library does not
+// provide this service so it is left to individual platforms to provide it.
+//
+// The contract is that the private key will be stored in an appropriate secure
+// system location, and be available to the SSLClientSocketOpenSSL when using a
+// client certificate created against the associated public key for client
+// authentication.
+class OpenSSLPrivateKeyStore {
+ public:
+ // Platforms must define this factory function as appropriate.
+ static OpenSSLPrivateKeyStore* GetInstance();
+
+ virtual ~OpenSSLPrivateKeyStore() {}
+
+ // Called to store a private key generated via <keygen> while visiting |url|.
+ // Does not takes ownership of |pkey|, the caller reamins responsible to
+ // EVP_PKEY_free it. (Internally, a copy maybe made or the reference count
+ // incremented).
+ // Returns false if an error occurred whilst attempting to store the key.
+ virtual bool StorePrivateKey(const GURL& url, EVP_PKEY* pkey) = 0;
+
+ // Given a |public_key| part returns the corresponding private key, or NULL
+ // if no key found. Does NOT return ownership.
+ virtual EVP_PKEY* FetchPrivateKey(EVP_PKEY* public_key) = 0;
+
+ protected:
+ OpenSSLPrivateKeyStore() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OpenSSLPrivateKeyStore);
+};
+
+} // namespace net
+
+#endif // NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_
diff --git a/net/base/registry_controlled_domain.h b/net/base/registry_controlled_domain.h
index fc64f3a..7586c12 100644
--- a/net/base/registry_controlled_domain.h
+++ b/net/base/registry_controlled_domain.h
@@ -198,6 +198,11 @@ class RegistryControlledDomainService {
static size_t GetRegistryLength(const std::wstring& host,
bool allow_unknown_registries);
+ // Returns the singleton instance, after attempting to initialize it.
+ // NOTE that if the effective-TLD data resource can't be found, the instance
+ // will be initialized and continue operation with simple default TLD data.
+ static RegistryControlledDomainService* GetInstance();
+
protected:
// The entire protected API is only for unit testing. I mean it. Don't make
// me come over there!
@@ -221,11 +226,6 @@ class RegistryControlledDomainService {
// To allow construction of the internal singleton instance.
friend struct DefaultSingletonTraits<RegistryControlledDomainService>;
- // Returns the singleton instance, after attempting to initialize it.
- // NOTE that if the effective-TLD data resource can't be found, the instance
- // will be initialized and continue operation with simple default TLD data.
- static RegistryControlledDomainService* GetInstance();
-
// Internal workings of the static public methods. See above.
static std::string GetDomainAndRegistryImpl(const std::string& host);
size_t GetRegistryLengthImpl(const std::string& host,
diff --git a/net/base/ssl_cert_request_info.cc b/net/base/ssl_cert_request_info.cc
index b7728e5..bb91632 100644
--- a/net/base/ssl_cert_request_info.cc
+++ b/net/base/ssl_cert_request_info.cc
@@ -11,11 +11,6 @@ namespace net {
SSLCertRequestInfo::SSLCertRequestInfo() {
}
-void SSLCertRequestInfo::Reset() {
- host_and_port.clear();
- client_certs.clear();
-}
-
SSLCertRequestInfo::~SSLCertRequestInfo() {
}
diff --git a/net/base/ssl_cert_request_info.h b/net/base/ssl_cert_request_info.h
index 416e902..22eecfe 100644
--- a/net/base/ssl_cert_request_info.h
+++ b/net/base/ssl_cert_request_info.h
@@ -22,9 +22,6 @@ class SSLCertRequestInfo
public:
SSLCertRequestInfo();
- // Resets the SSLCertRequestInfo as if no certificate had been requested.
- void Reset();
-
// The host and port of the SSL server that requested client authentication.
std::string host_and_port;
diff --git a/net/base/ssl_cipher_suite_names.cc b/net/base/ssl_cipher_suite_names.cc
index 39efd1c..eb6fe46 100644
--- a/net/base/ssl_cipher_suite_names.cc
+++ b/net/base/ssl_cipher_suite_names.cc
@@ -366,7 +366,7 @@ void SSLVersionToString(const char** name, int ssl_version) {
*name = "TLS 1.2";
break;
default:
- NOTREACHED();
+ NOTREACHED() << ssl_version;
*name = "???";
break;
}
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc
index 041c720..d6df3ea 100644
--- a/net/base/ssl_config_service.cc
+++ b/net/base/ssl_config_service.cc
@@ -20,11 +20,12 @@ SSLConfig::CertAndStatus::CertAndStatus() : cert_status(0) {}
SSLConfig::CertAndStatus::~CertAndStatus() {}
SSLConfig::SSLConfig()
- : rev_checking_enabled(true), ssl2_enabled(false), ssl3_enabled(true),
+ : rev_checking_enabled(true), ssl3_enabled(true),
tls1_enabled(true), dnssec_enabled(false), snap_start_enabled(false),
dns_cert_provenance_checking_enabled(false),
- mitm_proxies_allowed(false), false_start_enabled(true),
- send_client_cert(false), verify_ev_cert(false), ssl3_fallback(false) {
+ session_resume_disabled(false), mitm_proxies_allowed(false),
+ false_start_enabled(true), send_client_cert(false),
+ verify_ev_cert(false), ssl3_fallback(false) {
}
SSLConfig::~SSLConfig() {
@@ -173,7 +174,6 @@ void SSLConfigService::RemoveObserver(Observer* observer) {
void SSLConfigService::ProcessConfigUpdate(const SSLConfig& orig_config,
const SSLConfig& new_config) {
if (orig_config.rev_checking_enabled != new_config.rev_checking_enabled ||
- orig_config.ssl2_enabled != new_config.ssl2_enabled ||
orig_config.ssl3_enabled != new_config.ssl3_enabled ||
orig_config.tls1_enabled != new_config.tls1_enabled) {
FOR_EACH_OBSERVER(Observer, observer_list_, OnSSLConfigChanged());
diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h
index 0639f48..de2ebef 100644
--- a/net/base/ssl_config_service.h
+++ b/net/base/ssl_config_service.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.
@@ -18,13 +18,13 @@ namespace net {
// A collection of SSL-related configuration settings.
struct SSLConfig {
// Default to revocation checking.
- // Default to SSL 2.0 off, SSL 3.0 on, and TLS 1.0 on.
+ // Default to SSL 3.0 on and TLS 1.0 on.
SSLConfig();
~SSLConfig();
bool rev_checking_enabled; // True if server certificate revocation
// checking is enabled.
- bool ssl2_enabled; // True if SSL 2.0 is enabled.
+ // SSL 2.0 is not supported.
bool ssl3_enabled; // True if SSL 3.0 is enabled.
bool tls1_enabled; // True if TLS 1.0 is enabled.
bool dnssec_enabled; // True if we'll accept DNSSEC chains in certificates.
@@ -32,14 +32,22 @@ struct SSLConfig {
// True if we'll do async checks for certificate provenance using DNS.
bool dns_cert_provenance_checking_enabled;
- // Cipher suites which should be explicitly prevented from being used. By
- // default, all cipher suites supported by the underlying SSL implementation
- // will be enabled, except for:
+ // TODO(hclam): This option is used to simplify the SSLServerSocketNSS
+ // implementation and should be removed when session caching is implemented.
+ // See http://crbug.com/67236 for more details.
+ bool session_resume_disabled; // Don't allow session resume.
+
+ // Cipher suites which should be explicitly prevented from being used in
+ // addition to those disabled by the net built-in policy -- by default, all
+ // cipher suites supported by the underlying SSL implementation will be
+ // enabled except for:
// - Null encryption cipher suites.
// - Weak cipher suites: < 80 bits of security strength.
// - FORTEZZA cipher suites (obsolete).
// - IDEA cipher suites (RFC 5469 explains why).
// - Anonymous cipher suites.
+ // The ciphers listed in |disabled_cipher_suites| will be removed in addition
+ // to the above statically defined disable list.
//
// Though cipher suites are sent in TLS as "uint8 CipherSuite[2]", in
// big-endian form, they should be declared in host byte order, with the
@@ -47,7 +55,7 @@ struct SSLConfig {
// Ex: To disable TLS_RSA_WITH_RC4_128_MD5, specify 0x0004, while to
// disable TLS_ECDH_ECDSA_WITH_RC4_128_SHA, specify 0xC002.
//
- // TODO(rsleevi): Not implemented when using OpenSSL or Schannel.
+ // TODO(rsleevi): Not implemented when using Schannel.
std::vector<uint16> disabled_cipher_suites;
// True if we allow this connection to be MITM attacked. This sounds a little
@@ -112,7 +120,6 @@ class SSLConfigService : public base::RefCountedThreadSafe<SSLConfigService> {
// data in SSLConfig, just those that qualify as a user config change.
// The following settings are considered user changes:
// rev_checking_enabled
- // ssl2_enabled
// ssl3_enabled
// tls1_enabled
virtual void OnSSLConfigChanged() = 0;
@@ -181,7 +188,7 @@ class SSLConfigService : public base::RefCountedThreadSafe<SSLConfigService> {
virtual ~SSLConfigService();
// SetFlags sets the values of several flags based on global configuration.
- static void SetSSLConfigFlags(SSLConfig*);
+ static void SetSSLConfigFlags(SSLConfig* ssl_config);
// Process before/after config update.
void ProcessConfigUpdate(const SSLConfig& orig_config,
diff --git a/net/base/ssl_config_service_mac.cc b/net/base/ssl_config_service_mac.cc
index 148bba4..06f9555 100644
--- a/net/base/ssl_config_service_mac.cc
+++ b/net/base/ssl_config_service_mac.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 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.
@@ -17,7 +17,6 @@ namespace {
static const int kConfigUpdateInterval = 10; // seconds
-static const bool kSSL2EnabledDefaultValue = false;
static const bool kSSL3EnabledDefaultValue = true;
static const bool kTLS1EnabledDefaultValue = true;
@@ -27,7 +26,6 @@ static CFStringRef kOCSPStyleKey = CFSTR("OCSPStyle");
static CFStringRef kCRLStyleKey = CFSTR("CRLStyle");
static CFStringRef kNoneRevocationValue = CFSTR("None");
static CFStringRef kBestAttemptRevocationValue = CFSTR("BestAttempt");
-static CFStringRef kSSL2EnabledKey = CFSTR("org.chromium.ssl.ssl2");
static CFStringRef kSSL3EnabledKey = CFSTR("org.chromium.ssl.ssl3");
static CFStringRef kTLS1EnabledKey = CFSTR("org.chromium.ssl.tls1");
@@ -89,8 +87,6 @@ bool SSLConfigServiceMac::GetSSLConfigNow(SSLConfig* config) {
config->rev_checking_enabled = (RevocationStyleIsEnabled(kOCSPStyleKey) ||
RevocationStyleIsEnabled(kCRLStyleKey));
- config->ssl2_enabled = SSLVersionIsEnabled(kSSL2EnabledKey,
- kSSL2EnabledDefaultValue);
config->ssl3_enabled = SSLVersionIsEnabled(kSSL3EnabledKey,
kSSL3EnabledDefaultValue);
config->tls1_enabled = SSLVersionIsEnabled(kTLS1EnabledKey,
@@ -103,14 +99,6 @@ bool SSLConfigServiceMac::GetSSLConfigNow(SSLConfig* config) {
}
// static
-void SSLConfigServiceMac::SetSSL2Enabled(bool enabled) {
- CFPreferencesSetAppValue(kSSL2EnabledKey,
- enabled ? kCFBooleanTrue : kCFBooleanFalse,
- kCFPreferencesCurrentApplication);
- CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
-}
-
-// static
void SSLConfigServiceMac::SetSSL3Enabled(bool enabled) {
CFPreferencesSetAppValue(kSSL3EnabledKey,
enabled ? kCFBooleanTrue : kCFBooleanFalse,
diff --git a/net/base/ssl_config_service_mac.h b/net/base/ssl_config_service_mac.h
index 4524d95..2583e80 100644
--- a/net/base/ssl_config_service_mac.h
+++ b/net/base/ssl_config_service_mac.h
@@ -24,7 +24,6 @@ class SSLConfigServiceMac : public SSLConfigService {
// Setters. Can be called on any thread.
static void SetRevCheckingEnabled(bool enabled);
- static void SetSSL2Enabled(bool enabled);
static void SetSSL3Enabled(bool enabled);
static void SetTLS1Enabled(bool enabled);
diff --git a/net/base/ssl_config_service_mac_unittest.cc b/net/base/ssl_config_service_mac_unittest.cc
index c94f213..a933b1c 100644
--- a/net/base/ssl_config_service_mac_unittest.cc
+++ b/net/base/ssl_config_service_mac_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 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.
@@ -39,7 +39,6 @@ TEST(SSLConfigServiceMacTest, GetNowTest) {
// Verify that the constructor sets the correct default values.
net::SSLConfig config;
EXPECT_TRUE(config.rev_checking_enabled);
- EXPECT_FALSE(config.ssl2_enabled);
EXPECT_TRUE(config.ssl3_enabled);
EXPECT_TRUE(config.tls1_enabled);
@@ -69,19 +68,6 @@ TEST(SSLConfigServiceMacTest, SetTest) {
net::SSLConfigServiceMac::SetRevCheckingEnabled(
config_save.rev_checking_enabled);
- // Test SetSSL2Enabled.
- net::SSLConfigServiceMac::SetSSL2Enabled(true);
- rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
- EXPECT_TRUE(rv);
- EXPECT_TRUE(config.ssl2_enabled);
-
- net::SSLConfigServiceMac::SetSSL2Enabled(false);
- rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
- EXPECT_TRUE(rv);
- EXPECT_FALSE(config.ssl2_enabled);
-
- net::SSLConfigServiceMac::SetSSL2Enabled(config_save.ssl2_enabled);
-
// Test SetSSL3Enabled.
net::SSLConfigServiceMac::SetSSL3Enabled(true);
rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
@@ -147,15 +133,13 @@ TEST(SSLConfigServiceMacTest, ObserverTest) {
EXPECT_TRUE(rv);
net::SSLConfig config;
- net::SSLConfigServiceMac::SetSSL2Enabled(false);
- config_service->GetSSLConfigAt(&config, now);
// Add an observer.
SSLConfigServiceMacObserver observer;
config_service->AddObserver(&observer);
- // Toggle SSL2.
- net::SSLConfigServiceMac::SetSSL2Enabled(!config_save.ssl2_enabled);
+ // Toggle SSL3.
+ net::SSLConfigServiceMac::SetSSL3Enabled(!config_save.ssl3_enabled);
config_service->GetSSLConfigAt(&config, later);
// Verify that the observer was notified.
@@ -164,7 +148,7 @@ TEST(SSLConfigServiceMacTest, ObserverTest) {
// Remove the observer.
config_service->RemoveObserver(&observer);
- // Restore the original SSL2 setting.
- net::SSLConfigServiceMac::SetSSL2Enabled(config_save.ssl2_enabled);
+ // Restore the original SSL3 setting.
+ net::SSLConfigServiceMac::SetSSL3Enabled(config_save.ssl3_enabled);
}
diff --git a/net/base/ssl_config_service_win.cc b/net/base/ssl_config_service_win.cc
index d4153c3..aca0626 100644
--- a/net/base/ssl_config_service_win.cc
+++ b/net/base/ssl_config_service_win.cc
@@ -29,7 +29,6 @@ static const wchar_t kProtocolsValueName[] = L"SecureProtocols";
// The bits are OR'ed to form the DWORD value. So 0xa0 means SSL 3.0 and
// TLS 1.0.
enum {
- SSL2 = 0x08,
SSL3 = 0x20,
TLS1 = 0x80
};
@@ -77,7 +76,6 @@ bool SSLConfigServiceWin::GetSSLConfigNow(SSLConfig* config) {
protocols = PROTOCOLS_DEFAULT;
config->rev_checking_enabled = (revocation != 0);
- config->ssl2_enabled = ((protocols & SSL2) != 0);
config->ssl3_enabled = ((protocols & SSL3) != 0);
config->tls1_enabled = ((protocols & TLS1) != 0);
SSLConfigService::SetSSLConfigFlags(config);
@@ -96,6 +94,7 @@ bool SSLConfigServiceWin::GetSSLConfigNow(SSLConfig* config) {
void SSLConfigServiceWin::SetRevCheckingEnabled(bool enabled) {
// This registry access goes to disk and will slow down the IO thread.
// http://crbug.com/61455
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
DWORD value = enabled;
RegKey internet_settings(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
KEY_WRITE);
@@ -105,11 +104,6 @@ void SSLConfigServiceWin::SetRevCheckingEnabled(bool enabled) {
}
// static
-void SSLConfigServiceWin::SetSSL2Enabled(bool enabled) {
- SetSSLVersionEnabled(SSL2, enabled);
-}
-
-// static
void SSLConfigServiceWin::SetSSL3Enabled(bool enabled) {
SetSSLVersionEnabled(SSL3, enabled);
}
@@ -123,6 +117,7 @@ void SSLConfigServiceWin::SetTLS1Enabled(bool enabled) {
void SSLConfigServiceWin::SetSSLVersionEnabled(int version, bool enabled) {
// 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(HKEY_CURRENT_USER, kInternetSettingsSubKeyName,
KEY_READ | KEY_WRITE);
DWORD value;
diff --git a/net/base/ssl_config_service_win.h b/net/base/ssl_config_service_win.h
index e5eb862..6d5b29f 100644
--- a/net/base/ssl_config_service_win.h
+++ b/net/base/ssl_config_service_win.h
@@ -29,7 +29,6 @@ class SSLConfigServiceWin : public SSLConfigService {
// Setters. Can be called on any thread.
static void SetRevCheckingEnabled(bool enabled);
- static void SetSSL2Enabled(bool enabled);
static void SetSSL3Enabled(bool enabled);
static void SetTLS1Enabled(bool enabled);
diff --git a/net/base/ssl_config_service_win_unittest.cc b/net/base/ssl_config_service_win_unittest.cc
index 1db4cef..7669d99 100644
--- a/net/base/ssl_config_service_win_unittest.cc
+++ b/net/base/ssl_config_service_win_unittest.cc
@@ -39,7 +39,6 @@ TEST(SSLConfigServiceWinTest, GetNowTest) {
// Verify that the constructor sets the correct default values.
net::SSLConfig config;
EXPECT_EQ(true, config.rev_checking_enabled);
- EXPECT_EQ(false, config.ssl2_enabled);
EXPECT_EQ(true, config.ssl3_enabled);
EXPECT_EQ(true, config.tls1_enabled);
@@ -69,19 +68,6 @@ TEST(SSLConfigServiceWinTest, SetTest) {
net::SSLConfigServiceWin::SetRevCheckingEnabled(
config_save.rev_checking_enabled);
- // Test SetSSL2Enabled.
- net::SSLConfigServiceWin::SetSSL2Enabled(true);
- rv = net::SSLConfigServiceWin::GetSSLConfigNow(&config);
- EXPECT_TRUE(rv);
- EXPECT_TRUE(config.ssl2_enabled);
-
- net::SSLConfigServiceWin::SetSSL2Enabled(false);
- rv = net::SSLConfigServiceWin::GetSSLConfigNow(&config);
- EXPECT_TRUE(rv);
- EXPECT_FALSE(config.ssl2_enabled);
-
- net::SSLConfigServiceWin::SetSSL2Enabled(config_save.ssl2_enabled);
-
// Test SetSSL3Enabled.
net::SSLConfigServiceWin::SetSSL3Enabled(true);
rv = net::SSLConfigServiceWin::GetSSLConfigNow(&config);
@@ -147,15 +133,13 @@ TEST(SSLConfigServiceWinTest, ObserverTest) {
EXPECT_TRUE(rv);
net::SSLConfig config;
- net::SSLConfigServiceWin::SetSSL2Enabled(false);
- config_service->GetSSLConfigAt(&config, now);
// Add an observer.
SSLConfigServiceWinObserver observer;
config_service->AddObserver(&observer);
- // Toggle SSL2.
- net::SSLConfigServiceWin::SetSSL2Enabled(!config_save.ssl2_enabled);
+ // Toggle SSL3.
+ net::SSLConfigServiceWin::SetSSL3Enabled(!config_save.ssl3_enabled);
config_service->GetSSLConfigAt(&config, later);
// Verify that the observer was notified.
@@ -164,7 +148,7 @@ TEST(SSLConfigServiceWinTest, ObserverTest) {
// Remove the observer.
config_service->RemoveObserver(&observer);
- // Restore the original SSL2 setting.
- net::SSLConfigServiceWin::SetSSL2Enabled(config_save.ssl2_enabled);
+ // Restore the original SSL3 setting.
+ net::SSLConfigServiceWin::SetSSL3Enabled(config_save.ssl3_enabled);
}
diff --git a/net/base/ssl_false_start_blacklist.txt b/net/base/ssl_false_start_blacklist.txt
index 4ef94be..aec6142 100644
--- a/net/base/ssl_false_start_blacklist.txt
+++ b/net/base/ssl_false_start_blacklist.txt
@@ -174,7 +174,6 @@ amo-happy-patients.com
amo-signature.net
amo-top.net
ampecommerce.com
-amsbwm.org
amsi.alliedgroup.net
amwaylive.com
analytics.sonymusic.com
@@ -741,7 +740,6 @@ cmithun.dojiggy.com
cms.whereilive.com.au
cnw.albertaequestrian.com
cnw.hcbc.ca
-co-labs.org
codarts.nl
coddy.com
cofunds.co.uk
@@ -861,9 +859,7 @@ cwa.fandr.com
cwa.telecomputing.no
cwt.no
cwtnordic.com
-cyberobservatories.net
cybershoppersonline.com
-cybs.rogers.com
d-ikt.no
d-starjob.com
d115.de
@@ -883,7 +879,6 @@ datasettlement.com
datatel.com
davidson.edu
davisregional.com
-daymet.org
dbpn.com
dc.myflorida.com
dc110.4shared.com
@@ -936,7 +931,6 @@ district205.net
djmmusic.com
dl.com
dl.rakuten.co.jp
-dlese.org
dmgov.org
dmz.rgcweb.org
docmesa.com
@@ -1165,6 +1159,7 @@ europass.cz
europlan.ru
eurotax.at
events.sainc.com
+everbox.com
evergabe-online.info
evoline.net
evoraoralcaresite.com
@@ -1359,7 +1354,6 @@ geometrik.golder.se
geonosis.itsso.gc.ca
georgefox.edu
gepartsrebates.com
-gepon.org
germfree.org
get1931roadster.com
get1933caddy.com
@@ -1460,7 +1454,6 @@ ggusd.us
ggy.com
gilmorehealth.com
giltcdn.com
-gisclimatechange.org
global2.mtsallstream.com
glove.mizunoballpark.com
glowinghealth.com.au
@@ -2000,7 +1993,6 @@ leshamwowoffre.com
level.mol.hu
lexor.lsp.at
lexsan.vestingonline.nl
-lgelements.com
lh.k12.ar.us
library.failteireland.ie
liemerscollege.nl
@@ -2686,11 +2678,8 @@ myesafedepositbox.com
myevolver.com
myexterran.com
myfauquierhealth.org
-myflcourtaccess.com
myfldocs.com
myfloodonline.com
-myfloridacounty.com
-myfloridaremit.com
myfluvaccine.com
mygetmighytighty.com
mygiftregistry.co.za
@@ -2825,7 +2814,6 @@ nraesafe.com
nrwbank.com
ns002.toshiba-sol.co.jp
ns11mm.sept11mm.org
-nsdlnetwork.org
nsw.gov.au
nswmentors.com
ntdira.com
@@ -3534,7 +3522,6 @@ s-yoyaku.city.urayasu.chiba.jp
s.ixiaa.com
s.ncp.imrworldwide.com
s1defense.com
-s2task.globe.gov
saab-leadengine.de
saas.dynamate.eu
saas.it-telcom.nl
@@ -4042,7 +4029,6 @@ tc4men.com
tco.cfbt-inspections.com
tcspost.thomassen.com
tdj.ac.jp
-teachingboxes.org
teachingpersonnel.com
teambrandon.ca
tecdlr.com
@@ -4062,7 +4048,6 @@ terrabanking.romexterra.ro
testdrivereward.com
testdriveunlimited2.com
tewkesburyschool.org
-tfelements.com
tge.cl
tgn.co.jp
tgw.com
@@ -4154,7 +4139,6 @@ toranomon-ichiba.com
tosti-asia.com
totalcore.com
touchnbrush.tv
-touchnet.com
toutatice.fr
tpmail.transplace.com
tracs.txstate.edu
@@ -4233,7 +4217,6 @@ uab.edu
uatoa.americanexpress.com
ube-ind.co.jp
ubi.pt
-ucar.edu
ucf.edu
uci.edu
uckac.edu
@@ -4480,7 +4463,6 @@ wastis-eu.st.com
wcupa.edu
wcvpn.wartburg.edu
wdpartnersonline.com
-weathercoalition.org
web-opas.osakaya.co.jp
web-pl.daikin.co.jp
web-vpn.hefr.ch
diff --git a/net/base/test_root_certs.cc b/net/base/test_root_certs.cc
new file mode 100644
index 0000000..6d4bc18
--- /dev/null
+++ b/net/base/test_root_certs.cc
@@ -0,0 +1,59 @@
+// 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/base/test_root_certs.h"
+
+#include <string>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "net/base/x509_certificate.h"
+
+namespace net {
+
+namespace {
+
+bool g_has_instance = false;
+
+base::LazyInstance<TestRootCerts,
+ base::LeakyLazyInstanceTraits<TestRootCerts> >
+ g_test_root_certs(base::LINKER_INITIALIZED);
+
+CertificateList LoadCertificates(const FilePath& filename) {
+ std::string raw_cert;
+ if (!file_util::ReadFileToString(filename, &raw_cert)) {
+ LOG(ERROR) << "Can't load certificate " << filename.value();
+ return CertificateList();
+ }
+
+ return X509Certificate::CreateCertificateListFromBytes(
+ raw_cert.data(), raw_cert.length(), X509Certificate::FORMAT_AUTO);
+}
+
+} // namespace
+
+// static
+TestRootCerts* TestRootCerts::GetInstance() {
+ return g_test_root_certs.Pointer();
+}
+
+bool TestRootCerts::HasInstance() {
+ return g_has_instance;
+}
+
+bool TestRootCerts::AddFromFile(const FilePath& file) {
+ CertificateList root_certs = LoadCertificates(file);
+ if (root_certs.empty() || root_certs.size() > 1)
+ return false;
+
+ return Add(root_certs.front());
+}
+
+TestRootCerts::TestRootCerts() {
+ Init();
+ g_has_instance = true;
+}
+
+} // namespace net
diff --git a/net/base/test_root_certs.h b/net/base/test_root_certs.h
new file mode 100644
index 0000000..3fa8fcf
--- /dev/null
+++ b/net/base/test_root_certs.h
@@ -0,0 +1,103 @@
+// 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_BASE_TEST_ROOT_CERTS_H_
+#define NET_BASE_TEST_ROOT_CERTS_H_
+#pragma once
+
+#include "base/lazy_instance.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#include <wincrypt.h>
+#elif defined(OS_MACOSX)
+#include <CoreFoundation/CFArray.h>
+#include <Security/SecTrust.h>
+#include "base/mac/scoped_cftyperef.h"
+#elif defined(USE_NSS)
+#include <list>
+#endif
+
+class FilePath;
+
+namespace net {
+
+class X509Certificate;
+
+// TestRootCerts is a helper class for unit tests that is used to
+// artificially mark a certificate as trusted, independent of the local
+// machine configuration.
+class TestRootCerts {
+ public:
+ // Obtains the Singleton instance to the trusted certificates.
+ static TestRootCerts* GetInstance();
+
+ // Returns true if an instance exists, without forcing an initialization.
+ static bool HasInstance();
+
+ // Marks |certificate| as trusted for X509Certificate::Verify(). Returns
+ // false if the certificate could not be marked trusted.
+ bool Add(X509Certificate* certificate);
+
+ // Reads a single certificate from |file| and marks it as trusted. Returns
+ // false if an error is encountered, such as being unable to read |file|
+ // or more than one certificate existing in |file|.
+ bool AddFromFile(const FilePath& file);
+
+ // Clears the trusted status of any certificates that were previously
+ // marked trusted via Add().
+ void Clear();
+
+ // Returns true if there are no certificates that have been marked trusted.
+ bool IsEmpty() const;
+
+#if defined(OS_MACOSX)
+ CFArrayRef temporary_roots() const { return temporary_roots_; }
+
+ // Modifies the root certificates of |trust_ref| to include the
+ // certificates stored in |temporary_roots_|. If IsEmpty() is true, this
+ // does not modify |trust_ref|.
+ OSStatus FixupSecTrustRef(SecTrustRef trust_ref) const;
+#elif defined(OS_WIN)
+ HCERTSTORE temporary_roots() const { return temporary_roots_; }
+
+ // Returns an HCERTCHAINENGINE suitable to be used for certificate
+ // validation routines, or NULL to indicate that the default system chain
+ // engine is appropriate. The caller is responsible for freeing the
+ // returned HCERTCHAINENGINE.
+ HCERTCHAINENGINE GetChainEngine() const;
+#endif
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<TestRootCerts>;
+
+ TestRootCerts();
+ ~TestRootCerts();
+
+ // Performs platform-dependent initialization.
+ void Init();
+
+#if defined(OS_MACOSX)
+ base::mac::ScopedCFTypeRef<CFMutableArrayRef> temporary_roots_;
+#elif defined(OS_WIN)
+ HCERTSTORE temporary_roots_;
+#elif defined(USE_NSS)
+ // It is necessary to maintain a cache of the original certificate trust
+ // settings, in order to restore them when Clear() is called.
+ class TrustEntry;
+ std::list<TrustEntry*> trust_cache_;
+#endif
+
+#if defined(OS_WIN) || defined(USE_OPENSSL)
+ // True if there are no temporarily trusted root certificates.
+ bool empty_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(TestRootCerts);
+};
+
+} // namespace net
+
+#endif // NET_BASE_TEST_ROOT_CERTS_H_
diff --git a/net/base/test_root_certs_mac.cc b/net/base/test_root_certs_mac.cc
new file mode 100644
index 0000000..6a8611a
--- /dev/null
+++ b/net/base/test_root_certs_mac.cc
@@ -0,0 +1,135 @@
+// 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/base/test_root_certs.h"
+
+#include <Security/Security.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "net/base/x509_certificate.h"
+
+namespace net {
+
+namespace {
+
+#if !defined(MAC_OS_X_VERSION_10_6) || \
+ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
+// Declared in <Security/SecBase.h> of the 10.6 SDK.
+enum {
+ errSecUnimplemented = -4,
+};
+#endif
+
+typedef OSStatus (*SecTrustSetAnchorCertificatesOnlyFuncPtr)(SecTrustRef,
+ Boolean);
+
+Boolean OurSecCertificateEqual(const void* value1, const void* value2) {
+ if (CFGetTypeID(value1) != SecCertificateGetTypeID() ||
+ CFGetTypeID(value2) != SecCertificateGetTypeID())
+ return CFEqual(value1, value2);
+ return X509Certificate::IsSameOSCert(
+ reinterpret_cast<SecCertificateRef>(const_cast<void*>(value1)),
+ reinterpret_cast<SecCertificateRef>(const_cast<void*>(value2)));
+}
+
+const void* RetainWrapper(CFAllocatorRef unused, const void* value) {
+ return CFRetain(value);
+}
+
+void ReleaseWrapper(CFAllocatorRef unused, const void* value) {
+ CFRelease(value);
+}
+
+// CFEqual prior to 10.6 only performed pointer checks on SecCertificateRefs,
+// rather than checking if they were the same (logical) certificate, so a
+// custom structure is used for the array callbacks.
+const CFArrayCallBacks kCertArrayCallbacks = {
+ 0, // version
+ RetainWrapper,
+ ReleaseWrapper,
+ CFCopyDescription,
+ OurSecCertificateEqual,
+};
+
+} // namespace
+
+bool TestRootCerts::Add(X509Certificate* certificate) {
+ if (CFArrayContainsValue(temporary_roots_,
+ CFRangeMake(0, CFArrayGetCount(temporary_roots_)),
+ certificate->os_cert_handle()))
+ return true;
+ CFArrayAppendValue(temporary_roots_, certificate->os_cert_handle());
+ return true;
+}
+
+void TestRootCerts::Clear() {
+ CFArrayRemoveAllValues(temporary_roots_);
+}
+
+bool TestRootCerts::IsEmpty() const {
+ return CFArrayGetCount(temporary_roots_) == 0;
+}
+
+OSStatus TestRootCerts::FixupSecTrustRef(SecTrustRef trust_ref) const {
+ if (IsEmpty())
+ return noErr;
+
+ CFBundleRef bundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"));
+ SecTrustSetAnchorCertificatesOnlyFuncPtr set_anchor_certificates_only = NULL;
+ if (bundle) {
+ set_anchor_certificates_only =
+ reinterpret_cast<SecTrustSetAnchorCertificatesOnlyFuncPtr>(
+ CFBundleGetFunctionPointerForName(bundle,
+ CFSTR("SecTrustSetAnchorCertificatesOnly")));
+ }
+
+ OSStatus status = noErr;
+ if (set_anchor_certificates_only) {
+ // OS X 10.6 includes a function where the system trusts can be
+ // preserved while appending application trusts. This is preferable,
+ // because it preserves any user trust settings (explicit distrust),
+ // which the naive copy in 10.5 does not. Unfortunately, though the
+ // function pointer may be available, it is not always implemented. If it
+ // returns errSecUnimplemented, fall through to the 10.5 behaviour.
+ status = SecTrustSetAnchorCertificates(trust_ref, temporary_roots_);
+ if (status)
+ return status;
+ status = set_anchor_certificates_only(trust_ref, false);
+ if (status != errSecUnimplemented)
+ return status;
+
+ // Restore the original settings before falling back.
+ status = SecTrustSetAnchorCertificates(trust_ref, NULL);
+ if (status)
+ return status;
+ }
+
+ // On 10.5, the system certificates have to be copied and merged into
+ // the application trusts, and may override any user trust settings.
+ CFArrayRef system_roots = NULL;
+ status = SecTrustCopyAnchorCertificates(&system_roots);
+ if (status)
+ return status;
+
+ base::mac::ScopedCFTypeRef<CFArrayRef> scoped_system_roots(system_roots);
+ base::mac::ScopedCFTypeRef<CFMutableArrayRef> scoped_roots(
+ CFArrayCreateMutableCopy(kCFAllocatorDefault, 0,
+ scoped_system_roots));
+ DCHECK(scoped_roots.get());
+
+ CFArrayAppendArray(scoped_roots, temporary_roots_,
+ CFRangeMake(0, CFArrayGetCount(temporary_roots_)));
+ return SecTrustSetAnchorCertificates(trust_ref, scoped_roots);
+}
+
+TestRootCerts::~TestRootCerts() {}
+
+void TestRootCerts::Init() {
+ temporary_roots_.reset(CFArrayCreateMutable(kCFAllocatorDefault, 0,
+ &kCertArrayCallbacks));
+}
+
+} // namespace net
diff --git a/net/base/test_root_certs_nss.cc b/net/base/test_root_certs_nss.cc
new file mode 100644
index 0000000..ae5ff5c
--- /dev/null
+++ b/net/base/test_root_certs_nss.cc
@@ -0,0 +1,119 @@
+// 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/base/test_root_certs.h"
+
+#include <cert.h>
+
+#include "base/logging.h"
+#include "base/nss_util.h"
+#include "base/stl_util-inl.h"
+#include "net/base/x509_certificate.h"
+
+namespace net {
+
+// TrustEntry is used to store the original CERTCertificate and CERTCertTrust
+// for a certificate whose trust status has been changed by the
+// TestRootCerts.
+class TestRootCerts::TrustEntry {
+ public:
+ // Creates a new TrustEntry by incrementing the reference to |certificate|
+ // and copying |trust|.
+ TrustEntry(CERTCertificate* certificate, CERTCertTrust trust);
+ ~TrustEntry();
+
+ CERTCertificate* certificate() const { return certificate_; }
+ CERTCertTrust trust() const { return trust_; }
+
+ private:
+ // The temporary root certificate.
+ CERTCertificate* certificate_;
+
+ // The original trust settings, before |certificate_| was manipulated to
+ // be a temporarily trusted root.
+ CERTCertTrust trust_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrustEntry);
+};
+
+TestRootCerts::TrustEntry::TrustEntry(CERTCertificate* certificate,
+ CERTCertTrust trust)
+ : certificate_(CERT_DupCertificate(certificate)),
+ trust_(trust) {
+}
+
+TestRootCerts::TrustEntry::~TrustEntry() {
+ CERT_DestroyCertificate(certificate_);
+}
+
+bool TestRootCerts::Add(X509Certificate* certificate) {
+ // Preserve the original trust bits so that they can be restored when
+ // the certificate is removed.
+ CERTCertTrust original_trust;
+ SECStatus rv = CERT_GetCertTrust(certificate->os_cert_handle(),
+ &original_trust);
+ if (rv != SECSuccess) {
+ // CERT_GetCertTrust will fail if the certificate does not have any
+ // particular trust settings associated with it, and attempts to use
+ // |original_trust| later to restore the original trust settings will not
+ // cause the trust settings to be revoked. If the certificate has no
+ // particular trust settings associated with it, mark the certificate as
+ // a valid CA certificate with no specific trust.
+ rv = CERT_DecodeTrustString(&original_trust, "c,c,c");
+ }
+
+ // Change the trust bits to unconditionally trust this certificate.
+ CERTCertTrust new_trust;
+ rv = CERT_DecodeTrustString(&new_trust, "TCu,Cu,Tu");
+ if (rv != SECSuccess) {
+ LOG(ERROR) << "Cannot decode certificate trust string.";
+ return false;
+ }
+
+ rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
+ certificate->os_cert_handle(),
+ &new_trust);
+ if (rv != SECSuccess) {
+ LOG(ERROR) << "Cannot change certificate trust.";
+ return false;
+ }
+
+ trust_cache_.push_back(new TrustEntry(certificate->os_cert_handle(),
+ original_trust));
+ return true;
+}
+
+void TestRootCerts::Clear() {
+ // Restore the certificate trusts to what they were originally, before
+ // Add() was called. Work from the rear first, since if a certificate was
+ // added twice, the second entry's original trust status will be that of
+ // the first entry, while the first entry contains the desired resultant
+ // status.
+ for (std::list<TrustEntry*>::reverse_iterator it = trust_cache_.rbegin();
+ it != trust_cache_.rend(); ++it) {
+ CERTCertTrust original_trust = (*it)->trust();
+ SECStatus rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
+ (*it)->certificate(),
+ &original_trust);
+ // DCHECK(), rather than LOG(), as a failure to restore the original
+ // trust can cause flake or hard-to-trace errors in any unit tests that
+ // occur after Clear() has been called.
+ DCHECK_EQ(SECSuccess, rv) << "Cannot restore certificate trust.";
+ }
+ STLDeleteElements(&trust_cache_);
+}
+
+bool TestRootCerts::IsEmpty() const {
+ return trust_cache_.empty();
+}
+
+TestRootCerts::~TestRootCerts() {
+ Clear();
+}
+
+void TestRootCerts::Init() {
+ base::EnsureNSSInit();
+}
+
+} // namespace net
diff --git a/net/base/test_root_certs_openssl.cc b/net/base/test_root_certs_openssl.cc
new file mode 100644
index 0000000..8307703
--- /dev/null
+++ b/net/base/test_root_certs_openssl.cc
@@ -0,0 +1,51 @@
+// 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/base/test_root_certs.h"
+
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+
+#include "base/logging.h"
+#include "base/openssl_util.h"
+#include "base/tracked.h"
+#include "net/base/x509_certificate.h"
+
+namespace net {
+
+bool TestRootCerts::Add(X509Certificate* certificate) {
+ if (!X509_STORE_add_cert(X509Certificate::cert_store(),
+ certificate->os_cert_handle())) {
+ unsigned long error_code = ERR_peek_error();
+ if (ERR_GET_LIB(error_code) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error_code) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+ base::ClearOpenSSLERRStack(FROM_HERE);
+ return false;
+ }
+ ERR_clear_error();
+ }
+
+ empty_ = false;
+ return true;
+}
+
+void TestRootCerts::Clear() {
+ if (empty_)
+ return;
+
+ X509Certificate::ResetCertStore();
+ empty_ = true;
+}
+
+bool TestRootCerts::IsEmpty() const {
+ return empty_;
+}
+
+TestRootCerts::~TestRootCerts() {}
+
+void TestRootCerts::Init() {
+ empty_ = true;
+}
+
+} // namespace net
diff --git a/net/base/test_root_certs_win.cc b/net/base/test_root_certs_win.cc
new file mode 100644
index 0000000..7862e40
--- /dev/null
+++ b/net/base/test_root_certs_win.cc
@@ -0,0 +1,206 @@
+// 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/base/test_root_certs.h"
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include "base/basictypes.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "net/base/x509_certificate.h"
+
+namespace net {
+
+namespace {
+
+// Provides a CertDllOpenStoreProv callback provider function, to be called
+// by CertOpenStore when the CERT_STORE_PROV_SYSTEM_W store is opened. See
+// http://msdn.microsoft.com/en-us/library/aa376043(VS.85).aspx.
+BOOL WINAPI InterceptedOpenStoreW(LPCSTR store_provider,
+ DWORD encoding,
+ HCRYPTPROV crypt_provider,
+ DWORD flags,
+ const void* extra,
+ HCERTSTORE memory_store,
+ PCERT_STORE_PROV_INFO store_info);
+
+// CryptoAPIInjector is used to inject a store provider function for system
+// certificate stores before the one provided internally by Crypt32.dll.
+// Once injected, there is no way to remove, so every call to open a system
+// store will be redirected to the injected function.
+struct CryptoAPIInjector {
+ // The previous default function for opening system stores. For most
+ // configurations, this should point to Crypt32's internal
+ // I_CertDllOpenSystemStoreProvW function.
+ PFN_CERT_DLL_OPEN_STORE_PROV_FUNC original_function;
+
+ // The handle that CryptoAPI uses to ensure the DLL implementing
+ // |original_function| remains loaded in memory.
+ HCRYPTOIDFUNCADDR original_handle;
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<CryptoAPIInjector>;
+
+ CryptoAPIInjector()
+ : original_function(NULL),
+ original_handle(NULL) {
+ HCRYPTOIDFUNCSET registered_functions =
+ CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0);
+
+ // Preserve the original handler function in |original_function|. If other
+ // functions are overridden, they will also need to be preserved.
+ BOOL ok = CryptGetOIDFunctionAddress(
+ registered_functions, 0, CERT_STORE_PROV_SYSTEM_W, 0,
+ reinterpret_cast<void**>(&original_function), &original_handle);
+ DCHECK(ok);
+
+ // For now, intercept only the numeric form of the system store
+ // function, CERT_STORE_PROV_SYSTEM_W (0x0A), which is what Crypt32
+ // functionality uses exclusively. Depending on the machine that tests
+ // are being run on, it may prove necessary to also intercept
+ // sz_CERT_STORE_PROV_SYSTEM_[A/W] and CERT_STORE_PROV_SYSTEM_A, based
+ // on whether or not any third-party CryptoAPI modules have been
+ // installed.
+ const CRYPT_OID_FUNC_ENTRY kFunctionToIntercept =
+ { CERT_STORE_PROV_SYSTEM_W, &InterceptedOpenStoreW };
+
+ // Inject kFunctionToIntercept at the front of the linked list that
+ // crypt32 uses when CertOpenStore is called, replacing the existing
+ // registered function.
+ ok = CryptInstallOIDFunctionAddress(NULL, 0,
+ CRYPT_OID_OPEN_STORE_PROV_FUNC, 1,
+ &kFunctionToIntercept,
+ CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG);
+ DCHECK(ok);
+ }
+
+ // This is never called, because this object is intentionally leaked.
+ // Certificate verification happens on a non-joinable worker thread, which
+ // may still be running when ~AtExitManager is called, so the LazyInstance
+ // must be leaky.
+ ~CryptoAPIInjector() {
+ original_function = NULL;
+ CryptFreeOIDFunctionAddress(original_handle, NULL);
+ }
+};
+
+base::LazyInstance<CryptoAPIInjector,
+ base::LeakyLazyInstanceTraits<CryptoAPIInjector> >
+ g_capi_injector(base::LINKER_INITIALIZED);
+
+BOOL WINAPI InterceptedOpenStoreW(LPCSTR store_provider,
+ DWORD encoding,
+ HCRYPTPROV crypt_provider,
+ DWORD flags,
+ const void* store_name,
+ HCERTSTORE memory_store,
+ PCERT_STORE_PROV_INFO store_info) {
+ // If the high word is all zeroes, then |store_provider| is a numeric ID.
+ // Otherwise, it's a pointer to a null-terminated ASCII string. See the
+ // documentation for CryptGetOIDFunctionAddress for more information.
+ uint32 store_as_uint = reinterpret_cast<uint32>(store_provider);
+ if (store_as_uint > 0xFFFF || store_provider != CERT_STORE_PROV_SYSTEM_W ||
+ !g_capi_injector.Get().original_function)
+ return FALSE;
+
+ BOOL ok = g_capi_injector.Get().original_function(store_provider, encoding,
+ crypt_provider, flags,
+ store_name, memory_store,
+ store_info);
+ // Only the Root store should have certificates injected. If
+ // CERT_SYSTEM_STORE_RELOCATE_FLAG is set, then |store_name| points to a
+ // CERT_SYSTEM_STORE_RELOCATE_PARA structure, rather than a
+ // NULL-terminated wide string, so check before making a string
+ // comparison.
+ if (!ok || TestRootCerts::GetInstance()->IsEmpty() ||
+ (flags & CERT_SYSTEM_STORE_RELOCATE_FLAG) ||
+ lstrcmpiW(reinterpret_cast<LPCWSTR>(store_name), L"root"))
+ return ok;
+
+ // The result of CertOpenStore with CERT_STORE_PROV_SYSTEM_W is documented
+ // to be a collection store, and that appears to hold for |memory_store|.
+ // Attempting to add an individual certificate to |memory_store| causes
+ // the request to be forwarded to the first physical store in the
+ // collection that accepts modifications, which will cause a secure
+ // confirmation dialog to be displayed, confirming the user wishes to
+ // trust the certificate. However, appending a store to the collection
+ // will merely modify the temporary collection store, and will not persist
+ // any changes to the underlying physical store. When the |memory_store| is
+ // searched to see if a certificate is in the Root store, all the
+ // underlying stores in the collection will be searched, and any certificate
+ // in temporary_roots() will be found and seen as trusted.
+ return CertAddStoreToCollection(
+ memory_store, TestRootCerts::GetInstance()->temporary_roots(), 0, 0);
+}
+
+} // namespace
+
+bool TestRootCerts::Add(X509Certificate* certificate) {
+ // Ensure that the default CryptoAPI functionality has been intercepted.
+ // If a test certificate is never added, then no interception should
+ // happen.
+ g_capi_injector.Get();
+
+ BOOL ok = CertAddCertificateContextToStore(
+ temporary_roots_, certificate->os_cert_handle(),
+ CERT_STORE_ADD_NEW, NULL);
+ if (!ok) {
+ // If the certificate is already added, return successfully.
+ return GetLastError() == CRYPT_E_EXISTS;
+ }
+
+ empty_ = false;
+ return true;
+}
+
+void TestRootCerts::Clear() {
+ empty_ = true;
+
+ PCCERT_CONTEXT prev_cert = NULL;
+ while (prev_cert = CertEnumCertificatesInStore(temporary_roots_, NULL))
+ CertDeleteCertificateFromStore(prev_cert);
+}
+
+bool TestRootCerts::IsEmpty() const {
+ return empty_;
+}
+
+HCERTCHAINENGINE TestRootCerts::GetChainEngine() const {
+ if (IsEmpty())
+ return NULL; // Default chain engine will suffice.
+
+ // Each HCERTCHAINENGINE caches both the configured system stores and
+ // information about each chain that has been built. In order to ensure
+ // that changes to |temporary_roots_| are properly propagated and that the
+ // various caches are flushed, when at least one certificate is added,
+ // return a new chain engine for every call. Each chain engine creation
+ // should re-open the root store, ensuring the most recent changes are
+ // visible.
+ CERT_CHAIN_ENGINE_CONFIG engine_config = {
+ sizeof(engine_config)
+ };
+ engine_config.dwFlags =
+ CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE |
+ CERT_CHAIN_ENABLE_SHARE_STORE;
+ HCERTCHAINENGINE chain_engine = NULL;
+ BOOL ok = CertCreateCertificateChainEngine(&engine_config, &chain_engine);
+ DCHECK(ok);
+ return chain_engine;
+}
+
+TestRootCerts::~TestRootCerts() {
+ CertCloseStore(temporary_roots_, 0);
+}
+
+void TestRootCerts::Init() {
+ empty_ = true;
+ temporary_roots_ = CertOpenStore(
+ CERT_STORE_PROV_MEMORY, 0, NULL,
+ CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL);
+ DCHECK(temporary_roots_);
+}
+
+} // namespace net
diff --git a/net/base/transport_security_state.cc b/net/base/transport_security_state.cc
index 598ed48..258d59f 100644
--- a/net/base/transport_security_state.cc
+++ b/net/base/transport_security_state.cc
@@ -20,6 +20,8 @@
namespace net {
+const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year
+
TransportSecurityState::TransportSecurityState()
: delegate_(NULL) {
}
@@ -98,6 +100,24 @@ bool TransportSecurityState::IsEnabledForHost(DomainState* result,
return false;
}
+// MaxAgeToInt converts a string representation of a number of seconds into a
+// int. We use strtol in order to handle overflow correctly. The string may
+// contain an arbitary number which we should truncate correctly rather than
+// throwing a parse failure.
+static bool MaxAgeToInt(std::string::const_iterator begin,
+ std::string::const_iterator end,
+ int* result) {
+ const std::string s(begin, end);
+ char* endptr;
+ long int i = strtol(s.data(), &endptr, 10 /* base */);
+ if (*endptr || i < 0)
+ return false;
+ if (i > TransportSecurityState::kMaxHSTSAgeSecs)
+ i = TransportSecurityState::kMaxHSTSAgeSecs;
+ *result = i;
+ return true;
+}
+
// "Strict-Transport-Security" ":"
// "max-age" "=" delta-seconds [ ";" "includeSubDomains" ]
bool TransportSecurityState::ParseHeader(const std::string& value,
@@ -106,7 +126,7 @@ bool TransportSecurityState::ParseHeader(const std::string& value,
DCHECK(max_age);
DCHECK(include_subdomains);
- int max_age_candidate;
+ int max_age_candidate = 0;
enum ParserState {
START,
@@ -142,11 +162,9 @@ bool TransportSecurityState::ParseHeader(const std::string& value,
case AFTER_MAX_AGE_EQUALS:
if (IsAsciiWhitespace(*tokenizer.token_begin()))
continue;
- if (!base::StringToInt(tokenizer.token_begin(),
- tokenizer.token_end(),
- &max_age_candidate))
- return false;
- if (max_age_candidate < 0)
+ if (!MaxAgeToInt(tokenizer.token_begin(),
+ tokenizer.token_end(),
+ &max_age_candidate))
return false;
state = AFTER_MAX_AGE;
break;
@@ -411,8 +429,12 @@ bool TransportSecurityState::IsPreloadedSTS(
{19, true, "\015sunshinepress\003org"},
{21, false, "\003www\013noisebridge\003net"},
{10, false, "\004neg9\003org"},
+ {12, true, "\006riseup\003net"},
{11, false, "\006factor\002cc"},
- {19, true, "\015splendidbacon\003com"},
+ {22, false, "\007members\010mayfirst\003org"},
+ {22, false, "\007support\010mayfirst\003org"},
+ {17, false, "\002id\010mayfirst\003org"},
+ {20, false, "\005lists\010mayfirst\003org"},
};
static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
diff --git a/net/base/transport_security_state.h b/net/base/transport_security_state.h
index 49b44d7..fcd4e79 100644
--- a/net/base/transport_security_state.h
+++ b/net/base/transport_security_state.h
@@ -88,6 +88,9 @@ class TransportSecurityState :
bool Serialise(std::string* output);
bool Deserialise(const std::string& state, bool* dirty);
+ // The maximum number of seconds for which we'll cache an HSTS request.
+ static const long int kMaxHSTSAgeSecs;
+
private:
friend class base::RefCountedThreadSafe<TransportSecurityState>;
FRIEND_TEST_ALL_PREFIXES(TransportSecurityStateTest, IsPreloaded);
diff --git a/net/base/transport_security_state_unittest.cc b/net/base/transport_security_state_unittest.cc
index 126ca2b..3364bf1 100644
--- a/net/base/transport_security_state_unittest.cc
+++ b/net/base/transport_security_state_unittest.cc
@@ -116,18 +116,27 @@ TEST_F(TransportSecurityStateTest, ValidHeaders) {
EXPECT_TRUE(TransportSecurityState::ParseHeader(
"max-age=39408299 ;incLudesUbdOmains", &max_age, &include_subdomains));
- EXPECT_EQ(max_age, 39408299);
+ EXPECT_EQ(max_age,
+ std::min(TransportSecurityState::kMaxHSTSAgeSecs, 39408299l));
EXPECT_TRUE(include_subdomains);
EXPECT_TRUE(TransportSecurityState::ParseHeader(
"max-age=394082038 ; incLudesUbdOmains", &max_age, &include_subdomains));
- EXPECT_EQ(max_age, 394082038);
+ EXPECT_EQ(max_age,
+ std::min(TransportSecurityState::kMaxHSTSAgeSecs, 394082038l));
EXPECT_TRUE(include_subdomains);
EXPECT_TRUE(TransportSecurityState::ParseHeader(
" max-age=0 ; incLudesUbdOmains ", &max_age, &include_subdomains));
EXPECT_EQ(max_age, 0);
EXPECT_TRUE(include_subdomains);
+
+ EXPECT_TRUE(TransportSecurityState::ParseHeader(
+ " max-age=999999999999999999999999999999999999999999999 ;"
+ " incLudesUbdOmains ",
+ &max_age, &include_subdomains));
+ EXPECT_EQ(max_age, TransportSecurityState::kMaxHSTSAgeSecs);
+ EXPECT_TRUE(include_subdomains);
}
TEST_F(TransportSecurityStateTest, SimpleMatches) {
@@ -346,12 +355,17 @@ TEST_F(TransportSecurityStateTest, Preloaded) {
EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "neg9.org"));
EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "www.neg9.org"));
+ EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "riseup.net"));
+ EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "foo.riseup.net"));
+
EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "factor.cc"));
EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "www.factor.cc"));
- EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "splendidbacon.com"));
- EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "www.splendidbacon.com"));
- EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "foo.splendidbacon.com"));
+ EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "members.mayfirst.org"));
+ EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "support.mayfirst.org"));
+ EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "id.mayfirst.org"));
+ EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "lists.mayfirst.org"));
+ EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "www.mayfirst.org"));
}
TEST_F(TransportSecurityStateTest, LongNames) {
diff --git a/net/base/winsock_init.cc b/net/base/winsock_init.cc
index ccaf01c..41810ef 100644
--- a/net/base/winsock_init.cc
+++ b/net/base/winsock_init.cc
@@ -6,8 +6,8 @@
#include "net/base/winsock_init.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/singleton.h"
namespace {
@@ -37,12 +37,15 @@ class WinsockInitSingleton {
}
};
+static base::LazyInstance<WinsockInitSingleton> g_winsock_init_singleton(
+ base::LINKER_INITIALIZED);
+
} // namespace
namespace net {
void EnsureWinsockInit() {
- Singleton<WinsockInitSingleton>::get();
+ g_winsock_init_singleton.Get();
}
} // namespace net
diff --git a/net/base/x509_cert_types.cc b/net/base/x509_cert_types.cc
index cdfbdaa..6beb3ec 100644
--- a/net/base/x509_cert_types.cc
+++ b/net/base/x509_cert_types.cc
@@ -6,9 +6,27 @@
#include "net/base/x509_certificate.h"
#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_piece.h"
+#include "base/time.h"
namespace net {
+namespace {
+
+// Helper for ParseCertificateDate. |*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
+
CertPrincipal::CertPrincipal() {
}
@@ -75,4 +93,34 @@ bool CertPolicy::HasDeniedCert() const {
return !denied_.empty();
}
+bool ParseCertificateDate(const base::StringPiece& raw_date,
+ CertDateFormat format,
+ base::Time* time) {
+ size_t year_length = format == CERT_DATE_FORMAT_UTC_TIME ? 2 : 4;
+
+ if (raw_date.length() < 11 + year_length)
+ return false;
+
+ const char* field = raw_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)
+ return false;
+
+ *time = base::Time::FromUTCExploded(exploded);
+ return true;
+}
+
} // namespace net
diff --git a/net/base/x509_cert_types.h b/net/base/x509_cert_types.h
index f762e56..eb3ad60 100644
--- a/net/base/x509_cert_types.h
+++ b/net/base/x509_cert_types.h
@@ -18,6 +18,11 @@
#include <Security/x509defs.h>
#endif
+namespace base {
+class Time;
+class StringPiece;
+} // namespace base
+
namespace net {
class X509Certificate;
@@ -127,6 +132,23 @@ inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
}
#endif
+// A list of ASN.1 date/time formats that ParseCertificateDate() supports,
+// encoded in the canonical forms specified in RFC 2459/3280/5280.
+enum CertDateFormat {
+ // UTCTime: Format is YYMMDDHHMMSSZ
+ CERT_DATE_FORMAT_UTC_TIME,
+
+ // GeneralizedTime: Format is YYYYMMDDHHMMSSZ
+ CERT_DATE_FORMAT_GENERALIZED_TIME,
+};
+
+// Attempts to parse |raw_date|, an ASN.1 date/time string encoded as
+// |format|, and writes the result into |*time|. If an invalid date is
+// specified, or if parsing fails, returns false, and |*time| will not be
+// updated.
+bool ParseCertificateDate(const base::StringPiece& raw_date,
+ CertDateFormat format,
+ base::Time* time);
} // namespace net
#endif // NET_BASE_X509_CERT_TYPES_H_
diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h
index 763bf9d..98375db 100644
--- a/net/base/x509_certificate.h
+++ b/net/base/x509_certificate.h
@@ -36,6 +36,10 @@ struct CERTCertificateStr;
class Pickle;
+namespace base {
+class RSAPrivateKey;
+} // namespace base
+
namespace net {
class CertVerifyResult;
@@ -148,6 +152,29 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
int length,
int format);
+ // Create a self-signed certificate containing the public key in |key|.
+ // Subject, serial number and validity period are given as parameters.
+ // The certificate is signed by the private key in |key|. The hashing
+ // algorithm for the signature is SHA-1.
+ //
+ // |subject| is a distinguished name defined in RFC4514.
+ //
+ // An example:
+ // CN=Michael Wong,O=FooBar Corporation,DC=foobar,DC=com
+ //
+ // SECURUITY WARNING
+ //
+ // Using self-signed certificates has the following security risks:
+ // 1. Encryption without authentication and thus vulnerable to
+ // man-in-the-middle attacks.
+ // 2. Self-signed certificates cannot be revoked.
+ //
+ // Use this certificate only after the above risks are acknowledged.
+ static X509Certificate* CreateSelfSigned(base::RSAPrivateKey* key,
+ const std::string& subject,
+ uint32 serial_number,
+ base::TimeDelta valid_duration);
+
// Creates a X509Certificate from the ground up. Used by tests that simulate
// SSL connections.
X509Certificate(const std::string& subject, const std::string& issuer,
@@ -220,7 +247,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
static bool GetSSLClientCertificates(
const std::string& server_domain,
const std::vector<CertPrincipal>& valid_issuers,
- std::vector<scoped_refptr<X509Certificate> >* certs);
+ CertificateList* certs);
// Creates the chain of certs to use for this client identity cert.
CFArrayRef CreateClientCertificateChain() const;
@@ -266,6 +293,11 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
int flags,
CertVerifyResult* verify_result) const;
+ // This method returns the DER encoded certificate.
+ // If the return value is true then the DER encoded certificate is available.
+ // The content of the DER encoded certificate is written to |encoded|.
+ bool GetDEREncoded(std::string* encoded);
+
OSCertHandle os_cert_handle() const { return cert_handle_; }
// Returns true if two OSCertHandles refer to identical certificates.
@@ -289,6 +321,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
private:
friend class base::RefCountedThreadSafe<X509Certificate>;
+ friend class TestRootCerts; // For unit tests
FRIEND_TEST_ALL_PREFIXES(X509CertificateTest, Cache);
FRIEND_TEST_ALL_PREFIXES(X509CertificateTest, IntermediateCertificates);
@@ -308,6 +341,12 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
#endif
bool VerifyEV() const;
+#if defined(USE_OPENSSL)
+ // Resets the store returned by cert_store() to default state. Used by
+ // TestRootCerts to undo modifications.
+ static void ResetCertStore();
+#endif
+
// Calculates the SHA-1 fingerprint of the certificate. Returns an empty
// (all zero) fingerprint on failure.
static SHA1Fingerprint CalculateFingerprint(OSCertHandle cert_handle);
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index 5a5d457..fd965cb 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -17,6 +17,7 @@
#include "net/base/cert_status_flags.h"
#include "net/base/cert_verify_result.h"
#include "net/base/net_errors.h"
+#include "net/base/test_root_certs.h"
using base::mac::ScopedCFTypeRef;
using base::Time;
@@ -25,62 +26,6 @@ namespace net {
namespace {
-class MacTrustedCertificates {
- public:
- // Sets the trusted root certificate used by tests. Call with |cert| set
- // to NULL to clear the test certificate.
- void SetTestCertificate(X509Certificate* cert) {
- AutoLock lock(lock_);
- test_certificate_ = cert;
- }
-
- // Returns an array containing the trusted certificates for use with
- // SecTrustSetAnchorCertificates(). Returns NULL if the system-supplied
- // list of trust anchors is acceptable (that is, there is not test
- // certificate available). Ownership follows the Create Rule (caller
- // is responsible for calling CFRelease on the non-NULL result).
- CFArrayRef CopyTrustedCertificateArray() {
- AutoLock lock(lock_);
-
- if (!test_certificate_)
- return NULL;
-
- // Failure to copy the anchor certificates or add the test certificate
- // is non-fatal; SecTrustEvaluate() will use the system anchors instead.
- CFArrayRef anchor_array;
- OSStatus status = SecTrustCopyAnchorCertificates(&anchor_array);
- if (status)
- return NULL;
- ScopedCFTypeRef<CFArrayRef> scoped_anchor_array(anchor_array);
- CFMutableArrayRef merged_array = CFArrayCreateMutableCopy(
- kCFAllocatorDefault, 0, anchor_array);
- if (!merged_array)
- return NULL;
- CFArrayAppendValue(merged_array, test_certificate_->os_cert_handle());
-
- return merged_array;
- }
- private:
- friend struct base::DefaultLazyInstanceTraits<MacTrustedCertificates>;
-
- // Obtain an instance of MacTrustedCertificates via the singleton
- // interface.
- MacTrustedCertificates() : test_certificate_(NULL) { }
-
- // An X509Certificate object that may be appended to the list of
- // system trusted anchors.
- scoped_refptr<X509Certificate> test_certificate_;
-
- // The trusted cache may be accessed from multiple threads.
- mutable Lock lock_;
-
- DISALLOW_COPY_AND_ASSIGN(MacTrustedCertificates);
-};
-
-base::LazyInstance<MacTrustedCertificates,
- base::LeakyLazyInstanceTraits<MacTrustedCertificates> >
- g_mac_trusted_certificates(base::LINKER_INITIALIZED);
-
typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef,
CFDictionaryRef*);
@@ -222,9 +167,10 @@ void GetCertGeneralNamesForOID(X509Certificate::OSCertHandle cert_handle,
for (size_t field = 0; field < fields.num_of_fields; ++field) {
if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) {
CSSM_X509_EXTENSION_PTR cssm_ext =
- (CSSM_X509_EXTENSION_PTR)fields.fields[field].FieldValue.Data;
+ reinterpret_cast<CSSM_X509_EXTENSION_PTR>(
+ fields.fields[field].FieldValue.Data);
CE_GeneralNames* alt_name =
- (CE_GeneralNames*) cssm_ext->value.parsedValue;
+ reinterpret_cast<CE_GeneralNames*>(cssm_ext->value.parsedValue);
for (size_t name = 0; name < alt_name->numNames; ++name) {
const CE_GeneralName& name_struct = alt_name->generalName[name];
@@ -235,10 +181,9 @@ void GetCertGeneralNamesForOID(X509Certificate::OSCertHandle cert_handle,
// CE_GeneralNameType for more information.
if (name_struct.nameType == name_type) {
const CSSM_DATA& name_data = name_struct.name;
- std::string value =
- std::string(reinterpret_cast<std::string::value_type*>
- (name_data.Data),
- name_data.Length);
+ std::string value = std::string(
+ reinterpret_cast<const char*>(name_data.Data),
+ name_data.Length);
result->push_back(value);
}
}
@@ -257,43 +202,23 @@ void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle,
for (size_t field = 0; field < fields.num_of_fields; ++field) {
if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) {
- CSSM_X509_TIME* x509_time =
- reinterpret_cast<CSSM_X509_TIME *>
- (fields.fields[field].FieldValue.Data);
- std::string time_string =
- std::string(reinterpret_cast<std::string::value_type*>
- (x509_time->time.Data),
- x509_time->time.Length);
-
- DCHECK(x509_time->timeType == BER_TAG_UTC_TIME ||
- x509_time->timeType == BER_TAG_GENERALIZED_TIME);
-
- struct tm time;
- const char* parse_string;
- if (x509_time->timeType == BER_TAG_UTC_TIME)
- parse_string = "%y%m%d%H%M%SZ";
- else if (x509_time->timeType == BER_TAG_GENERALIZED_TIME)
- parse_string = "%y%m%d%H%M%SZ";
- else {
- // Those are the only two BER tags for time; if neither are used then
- // this is a rather broken cert.
+ CSSM_X509_TIME* x509_time = reinterpret_cast<CSSM_X509_TIME*>(
+ fields.fields[field].FieldValue.Data);
+ if (x509_time->timeType != BER_TAG_UTC_TIME &&
+ x509_time->timeType != BER_TAG_GENERALIZED_TIME) {
+ LOG(ERROR) << "Unsupported date/time format "
+ << x509_time->timeType;
return;
}
- strptime(time_string.c_str(), parse_string, &time);
-
- Time::Exploded exploded;
- exploded.year = time.tm_year + 1900;
- exploded.month = time.tm_mon + 1;
- exploded.day_of_week = time.tm_wday;
- exploded.day_of_month = time.tm_mday;
- exploded.hour = time.tm_hour;
- exploded.minute = time.tm_min;
- exploded.second = time.tm_sec;
- exploded.millisecond = 0;
-
- *result = Time::FromUTCExploded(exploded);
- break;
+ base::StringPiece time_string(
+ reinterpret_cast<const char*>(x509_time->time.Data),
+ x509_time->time.Length);
+ CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ?
+ CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
+ if (!ParseCertificateDate(time_string, format, result))
+ LOG(ERROR) << "Invalid certificate date/time " << time_string;
+ return;
}
}
}
@@ -334,7 +259,8 @@ OSStatus CreatePolicy(const CSSM_OID* policy_OID,
// Caller is responsible for releasing the value stored into *out_cert_chain.
OSStatus CopyCertChain(SecCertificateRef cert_handle,
CFArrayRef* out_cert_chain) {
- DCHECK(cert_handle && out_cert_chain);
+ DCHECK(cert_handle);
+ DCHECK(out_cert_chain);
// Create an SSL policy ref configured for client cert evaluation.
SecPolicyRef ssl_policy;
OSStatus result = X509Certificate::CreateSSLClientPolicy(&ssl_policy);
@@ -343,9 +269,9 @@ OSStatus CopyCertChain(SecCertificateRef cert_handle,
ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
// Create a SecTrustRef.
- ScopedCFTypeRef<CFArrayRef> input_certs(
- CFArrayCreate(NULL, (const void**)&cert_handle, 1,
- &kCFTypeArrayCallBacks));
+ ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate(
+ NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)),
+ 1, &kCFTypeArrayCallBacks));
SecTrustRef trust_ref = NULL;
result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref);
if (result)
@@ -400,8 +326,8 @@ void AddCertificatesFromBytes(const char* data, size_t length,
X509Certificate::OSCertHandles* output) {
SecExternalFormat input_format = format;
ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy(
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
- length, kCFAllocatorNull));
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length,
+ kCFAllocatorNull));
CFArrayRef items = NULL;
OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format,
@@ -445,20 +371,15 @@ void AddCertificatesFromBytes(const char* data, size_t length,
} // namespace
-void SetMacTestCertificate(X509Certificate* cert) {
- g_mac_trusted_certificates.Get().SetTestCertificate(cert);
-}
-
void X509Certificate::Initialize() {
const CSSM_X509_NAME* name;
OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
- if (!status) {
+ if (!status)
subject_.Parse(name);
- }
+
status = SecCertificateGetIssuer(cert_handle_, &name);
- if (!status) {
+ if (!status)
issuer_.Parse(name);
- }
GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore,
&valid_start_);
@@ -479,6 +400,16 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
return CreateFromBytes(data, length);
}
+// static
+X509Certificate* X509Certificate::CreateSelfSigned(
+ base::RSAPrivateKey* key,
+ const std::string& subject,
+ uint32 serial_number,
+ base::TimeDelta valid_duration) {
+ // TODO(port): Implement.
+ return NULL;
+}
+
void X509Certificate::Persist(Pickle* pickle) {
CSSM_DATA cert_data;
OSStatus status = SecCertificateGetData(cert_handle_, &cert_data);
@@ -548,13 +479,8 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
return NetErrorFromOSStatus(status);
ScopedCFTypeRef<SecTrustRef> scoped_trust_ref(trust_ref);
- // Set the trusted anchor certificates for the SecTrustRef by merging the
- // system trust anchors and the test root certificate.
- CFArrayRef anchor_array =
- g_mac_trusted_certificates.Get().CopyTrustedCertificateArray();
- ScopedCFTypeRef<CFArrayRef> scoped_anchor_array(anchor_array);
- if (anchor_array) {
- status = SecTrustSetAnchorCertificates(trust_ref, anchor_array);
+ if (TestRootCerts::HasInstance()) {
+ status = TestRootCerts::GetInstance()->FixupSecTrustRef(trust_ref);
if (status)
return NetErrorFromOSStatus(status);
}
@@ -659,9 +585,8 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
if (cert_status == CERT_STATUS_COMMON_NAME_INVALID) {
std::vector<std::string> names;
GetDNSNames(&names);
- if (OverrideHostnameMismatch(hostname, &names)) {
+ if (OverrideHostnameMismatch(hostname, &names))
cert_status = 0;
- }
}
verify_result->cert_status |= cert_status;
}
@@ -682,9 +607,8 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
if (status)
return NetErrorFromOSStatus(status);
verify_result->cert_status |= CertStatusFromOSStatus(cssm_result);
- if (!verify_result->cert_status) {
+ if (!verify_result->cert_status)
verify_result->cert_status |= CERT_STATUS_INVALID;
- }
break;
}
@@ -727,6 +651,17 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
return OK;
}
+bool X509Certificate::GetDEREncoded(std::string* encoded) {
+ encoded->clear();
+ CSSM_DATA der_data;
+ if(SecCertificateGetData(cert_handle_, &der_data) == noErr) {
+ encoded->append(reinterpret_cast<char*>(der_data.Data),
+ der_data.Length);
+ return true;
+ }
+ return false;
+}
+
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
@@ -818,8 +753,8 @@ SHA1Fingerprint X509Certificate::CalculateFingerprint(
if (status)
return sha1;
- DCHECK(NULL != cert_data.Data);
- DCHECK(0 != cert_data.Length);
+ DCHECK(cert_data.Data);
+ DCHECK_NE(cert_data.Length, 0U);
CC_SHA1(cert_data.Data, cert_data.Length, sha1.data);
@@ -870,7 +805,7 @@ bool X509Certificate::IsIssuedBy(
CFArrayRef cert_chain = NULL;
OSStatus result;
result = CopyCertChain(os_cert_handle(), &cert_chain);
- if (result != noErr)
+ if (result)
return false;
ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain);
@@ -906,20 +841,22 @@ OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) {
}
// static
-bool X509Certificate::GetSSLClientCertificates (
+bool X509Certificate::GetSSLClientCertificates(
const std::string& server_domain,
const std::vector<CertPrincipal>& valid_issuers,
- std::vector<scoped_refptr<X509Certificate> >* certs) {
+ CertificateList* certs) {
ScopedCFTypeRef<SecIdentityRef> preferred_identity;
if (!server_domain.empty()) {
// See if there's an identity preference for this domain:
ScopedCFTypeRef<CFStringRef> domain_str(
base::SysUTF8ToCFStringRef("https://" + server_domain));
SecIdentityRef identity = NULL;
- if (SecIdentityCopyPreference(domain_str,
- 0,
- NULL, // validIssuers argument is ignored :(
- &identity) == noErr)
+ // While SecIdentityCopyPreferences appears to take a list of CA issuers
+ // to restrict the identity search to, within Security.framework the
+ // argument is ignored and filtering unimplemented. See
+ // SecIdentity.cpp in libsecurity_keychain, specifically
+ // _SecIdentityCopyPreferenceMatchingName().
+ if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr)
preferred_identity.reset(identity);
}
@@ -997,8 +934,10 @@ CFArrayRef X509Certificate::CreateClientCertificateChain() const {
CFArrayRef cert_chain = NULL;
result = CopyCertChain(cert_handle_, &cert_chain);
- if (result)
- goto exit;
+ if (result) {
+ LOG(ERROR) << "CreateIdentityCertificateChain error " << result;
+ return chain.release();
+ }
// Append the intermediate certs from SecTrust to the result array:
if (cert_chain) {
@@ -1010,9 +949,7 @@ CFArrayRef X509Certificate::CreateClientCertificateChain() const {
}
CFRelease(cert_chain);
}
-exit:
- if (result)
- LOG(ERROR) << "CreateIdentityCertificateChain error " << result;
+
return chain.release();
}
diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc
index 5061238..05e736c 100644
--- a/net/base/x509_certificate_nss.cc
+++ b/net/base/x509_certificate_nss.cc
@@ -5,6 +5,8 @@
#include "net/base/x509_certificate.h"
#include <cert.h>
+#include <cryptohi.h>
+#include <keyhi.h>
#include <nss.h>
#include <pk11pub.h>
#include <prerror.h>
@@ -14,6 +16,7 @@
#include <sechash.h>
#include <sslerr.h>
+#include "base/crypto/rsa_private_key.h"
#include "base/logging.h"
#include "base/pickle.h"
#include "base/scoped_ptr.h"
@@ -604,6 +607,108 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
return CreateFromBytes(data, length);
}
+// static
+X509Certificate* X509Certificate::CreateSelfSigned(
+ base::RSAPrivateKey* key,
+ const std::string& subject,
+ uint32 serial_number,
+ base::TimeDelta valid_duration) {
+ DCHECK(key);
+
+ // Create info about public key.
+ CERTSubjectPublicKeyInfo* spki =
+ SECKEY_CreateSubjectPublicKeyInfo(key->public_key());
+ if (!spki)
+ return NULL;
+
+ // Create the certificate request.
+ CERTName* subject_name =
+ CERT_AsciiToName(const_cast<char*>(subject.c_str()));
+ CERTCertificateRequest* cert_request =
+ CERT_CreateCertificateRequest(subject_name, spki, NULL);
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+
+ if (!cert_request) {
+ PRErrorCode prerr = PR_GetError();
+ LOG(ERROR) << "Failed to create certificate request: " << prerr;
+ CERT_DestroyName(subject_name);
+ return NULL;
+ }
+
+ PRTime now = PR_Now();
+ PRTime not_after = now + valid_duration.InMicroseconds();
+
+ // Note that the time is now in micro-second unit.
+ CERTValidity* validity = CERT_CreateValidity(now, not_after);
+ CERTCertificate* cert = CERT_CreateCertificate(serial_number, subject_name,
+ validity, cert_request);
+ if (!cert) {
+ PRErrorCode prerr = PR_GetError();
+ LOG(ERROR) << "Failed to create certificate: " << prerr;
+ }
+
+ // Cleanup for resources used to generate the cert.
+ CERT_DestroyName(subject_name);
+ CERT_DestroyValidity(validity);
+ CERT_DestroyCertificateRequest(cert_request);
+
+ // Sign the cert here. The logic of this method references SignCert() in NSS
+ // utility certutil: http://mxr.mozilla.org/security/ident?i=SignCert.
+
+ // |arena| is used to encode the cert.
+ PRArenaPool* arena = cert->arena;
+ SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->key()->keyType,
+ SEC_OID_SHA1);
+ if (algo_id == SEC_OID_UNKNOWN) {
+ CERT_DestroyCertificate(cert);
+ return NULL;
+ }
+
+ SECStatus rv = SECOID_SetAlgorithmID(arena, &cert->signature, algo_id, 0);
+ if (rv != SECSuccess) {
+ CERT_DestroyCertificate(cert);
+ return NULL;
+ }
+
+ // Generate a cert of version 3.
+ *(cert->version.data) = 2;
+ cert->version.len = 1;
+
+ SECItem der;
+ der.len = 0;
+ der.data = NULL;
+
+ // Use ASN1 DER to encode the cert.
+ void* encode_result = SEC_ASN1EncodeItem(
+ arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate));
+ if (!encode_result) {
+ CERT_DestroyCertificate(cert);
+ return NULL;
+ }
+
+ // Allocate space to contain the signed cert.
+ SECItem* result = SECITEM_AllocItem(arena, NULL, 0);
+ if (!result) {
+ CERT_DestroyCertificate(cert);
+ return NULL;
+ }
+
+ // Sign the ASN1 encoded cert and save it to |result|.
+ rv = SEC_DerSignData(arena, result, der.data, der.len, key->key(), algo_id);
+ if (rv != SECSuccess) {
+ CERT_DestroyCertificate(cert);
+ return NULL;
+ }
+
+ // Save the signed result to the cert.
+ cert->derCert = *result;
+
+ X509Certificate* x509_cert =
+ CreateFromHandle(cert, SOURCE_LONE_CERT_IMPORT, OSCertHandles());
+ CERT_DestroyCertificate(cert);
+ return x509_cert;
+}
+
void X509Certificate::Persist(Pickle* pickle) {
pickle->WriteData(reinterpret_cast<const char*>(cert_handle_->derCert.data),
cert_handle_->derCert.len);
@@ -724,6 +829,15 @@ bool X509Certificate::VerifyEV() const {
return true;
}
+bool X509Certificate::GetDEREncoded(std::string* encoded) {
+ if (!cert_handle_->derCert.len)
+ return false;
+ encoded->clear();
+ encoded->append(reinterpret_cast<char*>(cert_handle_->derCert.data),
+ cert_handle_->derCert.len);
+ return true;
+}
+
// static
bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
X509Certificate::OSCertHandle b) {
diff --git a/net/base/x509_certificate_openssl.cc b/net/base/x509_certificate_openssl.cc
index 5b2d365..4c339fc 100644
--- a/net/base/x509_certificate_openssl.cc
+++ b/net/base/x509_certificate_openssl.cc
@@ -206,7 +206,7 @@ void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
class X509InitSingleton {
public:
- static X509InitSingleton* Get() {
+ static X509InitSingleton* GetInstance() {
// We allow the X509 store to leak, because it is used from a non-joinable
// worker that is not stopped on shutdown, hence may still be using
// OpenSSL library after the AtExit runner has completed.
@@ -216,16 +216,20 @@ class X509InitSingleton {
int der_cache_ex_index() const { return der_cache_ex_index_; }
X509_STORE* store() const { return store_.get(); }
+ void ResetCertStore() {
+ store_.reset(X509_STORE_new());
+ DCHECK(store_.get());
+ X509_STORE_set_default_paths(store_.get());
+ // TODO(joth): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)).
+ }
+
private:
friend struct DefaultSingletonTraits<X509InitSingleton>;
- X509InitSingleton()
- : der_cache_ex_index_((base::EnsureOpenSSLInit(),
- X509_get_ex_new_index(0, 0, 0, 0,
- DERCache_free))),
- store_(X509_STORE_new()) {
+ X509InitSingleton() {
+ base::EnsureOpenSSLInit();
+ der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free);
DCHECK_NE(der_cache_ex_index_, -1);
- X509_STORE_set_default_paths(store_.get());
- // TODO(joth): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)).
+ ResetCertStore();
}
int der_cache_ex_index_;
@@ -259,7 +263,8 @@ DERCache* SetDERCache(X509Certificate::OSCertHandle cert,
// not free it).
bool GetDERAndCacheIfNeeded(X509Certificate::OSCertHandle cert,
DERCache* der_cache) {
- int x509_der_cache_index = X509InitSingleton::Get()->der_cache_ex_index();
+ int x509_der_cache_index =
+ X509InitSingleton::GetInstance()->der_cache_ex_index();
// Re-encoding the DER data via i2d_X509 is an expensive operation, but it's
// necessary for comparing two certificates. We re-encode at most once per
@@ -311,6 +316,11 @@ void X509Certificate::Initialize() {
nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_);
}
+// static
+void X509Certificate::ResetCertStore() {
+ X509InitSingleton::GetInstance()->ResetCertStore();
+}
+
SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) {
SHA1Fingerprint sha1;
unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data));
@@ -372,6 +382,16 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
return CreateFromBytes(data, length);
}
+// static
+X509Certificate* X509Certificate::CreateSelfSigned(
+ base::RSAPrivateKey* key,
+ const std::string& subject,
+ uint32 serial_number,
+ base::TimeDelta valid_duration) {
+ // TODO(port): Implement.
+ return NULL;
+}
+
void X509Certificate::Persist(Pickle* pickle) {
DERCache der_cache;
if (!GetDERAndCacheIfNeeded(cert_handle_, &der_cache))
@@ -392,7 +412,7 @@ void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
// static
X509_STORE* X509Certificate::cert_store() {
- return X509InitSingleton::Get()->store();
+ return X509InitSingleton::GetInstance()->store();
}
#ifndef ANDROID
@@ -426,19 +446,26 @@ int X509Certificate::Verify(const std::string& hostname,
cert_handle_, intermediates.get());
CHECK_EQ(1, rv);
- if (X509_verify_cert(ctx.get()) == 1) {
- return OK;
+ if (X509_verify_cert(ctx.get()) != 1) {
+ int x509_error = X509_STORE_CTX_get_error(ctx.get());
+ int cert_status = MapCertErrorToCertStatus(x509_error);
+ LOG(ERROR) << "X509 Verification error "
+ << X509_verify_cert_error_string(x509_error)
+ << " : " << x509_error
+ << " : " << X509_STORE_CTX_get_error_depth(ctx.get())
+ << " : " << cert_status;
+ verify_result->cert_status |= cert_status;
}
- int x509_error = X509_STORE_CTX_get_error(ctx.get());
- int cert_status = MapCertErrorToCertStatus(x509_error);
- LOG(ERROR) << "X509 Verification error "
- << X509_verify_cert_error_string(x509_error)
- << " : " << x509_error
- << " : " << X509_STORE_CTX_get_error_depth(ctx.get())
- << " : " << cert_status;
- verify_result->cert_status |= cert_status;
- return MapCertStatusToNetError(verify_result->cert_status);
+ if (IsCertStatusError(verify_result->cert_status))
+ return MapCertStatusToNetError(verify_result->cert_status);
+
+ return OK;
+}
+
+bool X509Certificate::GetDEREncoded(std::string* encoded) {
+ // TODO(port): Implement.
+ return false;
}
#endif
diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc
index 31173e4..dba5ef3 100644
--- a/net/base/x509_certificate_unittest.cc
+++ b/net/base/x509_certificate_unittest.cc
@@ -1,7 +1,8 @@
-// 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.
+#include "base/crypto/rsa_private_key.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
@@ -11,6 +12,7 @@
#include "net/base/cert_verify_result.h"
#include "net/base/net_errors.h"
#include "net/base/test_certificate_data.h"
+#include "net/base/test_root_certs.h"
#include "net/base/x509_certificate.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -161,30 +163,6 @@ const CertificateFormatTestData FormatTestData[] = {
NULL, } },
};
-// Returns a FilePath object representing the src/net/data/ssl/certificates
-// directory in the source tree.
-FilePath GetTestCertsDirectory() {
- FilePath certs_dir;
- PathService::Get(base::DIR_SOURCE_ROOT, &certs_dir);
- certs_dir = certs_dir.AppendASCII("net");
- certs_dir = certs_dir.AppendASCII("data");
- certs_dir = certs_dir.AppendASCII("ssl");
- certs_dir = certs_dir.AppendASCII("certificates");
- return certs_dir;
-}
-
-// Imports a certificate file in the src/net/data/ssl/certificates directory.
-// certs_dir represents the test certificates directory. cert_file is the
-// name of the certificate file.
-X509Certificate* ImportCertFromFile(const FilePath& certs_dir,
- const std::string& cert_file) {
- FilePath cert_path = certs_dir.AppendASCII(cert_file);
- std::string cert_data;
- if (!file_util::ReadFileToString(cert_path, &cert_data))
- return NULL;
- return X509Certificate::CreateFromBytes(cert_data.data(), cert_data.size());
-}
-
CertificateList CreateCertificateListFromFile(
const FilePath& certs_dir,
const std::string& cert_file,
@@ -427,13 +405,8 @@ TEST(X509CertificateTest, UnoSoftCertParsing) {
EXPECT_NE(0, verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
}
-#if defined(USE_NSS) || defined(USE_OPENSSL)
// A regression test for http://crbug.com/31497.
// This certificate will expire on 2012-04-08.
-// TODO(wtc): we can't run this test on Mac because MacTrustedCertificates
-// can hold only one additional trusted root certificate for unit tests.
-// TODO(wtc): we can't run this test on Windows because LoadTemporaryRootCert
-// isn't implemented (http//crbug.com/8470).
TEST(X509CertificateTest, IntermediateCARequireExplicitPolicy) {
FilePath certs_dir = GetTestCertsDirectory();
@@ -448,9 +421,8 @@ TEST(X509CertificateTest, IntermediateCARequireExplicitPolicy) {
ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
FilePath root_cert_path = certs_dir.AppendASCII("dod_root_ca_2_cert.der");
- scoped_refptr<X509Certificate> root_cert =
- LoadTemporaryRootCert(root_cert_path);
- ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert);
+ TestRootCerts* root_certs = TestRootCerts::GetInstance();
+ ASSERT_TRUE(root_certs->AddFromFile(root_cert_path));
X509Certificate::OSCertHandles intermediates;
intermediates.push_back(intermediate_cert->os_cert_handle());
@@ -464,8 +436,8 @@ TEST(X509CertificateTest, IntermediateCARequireExplicitPolicy) {
int error = cert_chain->Verify("www.us.army.mil", flags, &verify_result);
EXPECT_EQ(OK, error);
EXPECT_EQ(0, verify_result.cert_status);
+ root_certs->Clear();
}
-#endif
// Tests X509Certificate::Cache via X509Certificate::CreateFromHandle. We
// call X509Certificate::CreateFromHandle several times and observe whether
@@ -687,6 +659,33 @@ TEST(X509CertificateTest, IsIssuedBy) {
}
#endif // defined(OS_MACOSX)
+#if defined(USE_NSS) || defined(OS_WIN)
+// This test creates a signed cert from a private key and then verify content
+// of the certificate.
+TEST(X509CertificateTest, CreateSelfSigned) {
+ scoped_ptr<base::RSAPrivateKey> private_key(
+ base::RSAPrivateKey::Create(1024));
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateSelfSigned(
+ private_key.get(), "CN=subject", 1, base::TimeDelta::FromDays(1));
+
+ EXPECT_EQ("subject", cert->subject().GetDisplayName());
+ EXPECT_FALSE(cert->HasExpired());
+}
+
+TEST(X509CertificateTest, GetDEREncoded) {
+ scoped_ptr<base::RSAPrivateKey> private_key(
+ base::RSAPrivateKey::Create(1024));
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateSelfSigned(
+ private_key.get(), "CN=subject", 0, base::TimeDelta::FromDays(1));
+
+ std::string der_cert;
+ EXPECT_TRUE(cert->GetDEREncoded(&der_cert));
+ EXPECT_FALSE(der_cert.empty());
+}
+#endif
+
class X509CertificateParseTest
: public testing::TestWithParam<CertificateFormatTestData> {
public:
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
index 75cdf40..663563d 100644
--- a/net/base/x509_certificate_win.cc
+++ b/net/base/x509_certificate_win.cc
@@ -4,9 +4,11 @@
#include "net/base/x509_certificate.h"
+#include "base/crypto/rsa_private_key.h"
+#include "base/crypto/scoped_capi_types.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/pickle.h"
-#include "base/singleton.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
@@ -15,6 +17,7 @@
#include "net/base/ev_root_ca_metadata.h"
#include "net/base/net_errors.h"
#include "net/base/scoped_cert_chain_context.h"
+#include "net/base/test_root_certs.h"
#pragma comment(lib, "crypt32.lib")
@@ -24,6 +27,21 @@ namespace net {
namespace {
+typedef base::ScopedCAPIHandle<
+ HCERTSTORE,
+ base::CAPIDestroyerWithFlags<HCERTSTORE,
+ CertCloseStore, 0> > ScopedHCERTSTORE;
+
+struct FreeChainEngineFunctor {
+ void operator()(HCERTCHAINENGINE engine) const {
+ if (engine)
+ CertFreeCertificateChainEngine(engine);
+ }
+};
+
+typedef base::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor>
+ ScopedHCERTCHAINENGINE;
+
//-----------------------------------------------------------------------------
// TODO(wtc): This is a copy of the MapSecurityError function in
@@ -484,6 +502,70 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
return cert;
}
+// static
+X509Certificate* X509Certificate::CreateSelfSigned(
+ base::RSAPrivateKey* key,
+ const std::string& subject,
+ uint32 serial_number,
+ base::TimeDelta valid_duration) {
+ // Get the ASN.1 encoding of the certificate subject.
+ std::wstring w_subject = ASCIIToWide(subject);
+ DWORD encoded_subject_length = 0;
+ if (!CertStrToName(
+ X509_ASN_ENCODING,
+ const_cast<wchar_t*>(w_subject.c_str()),
+ CERT_X500_NAME_STR, NULL, NULL, &encoded_subject_length, NULL)) {
+ return NULL;
+ }
+
+ scoped_array<char> encoded_subject(new char[encoded_subject_length]);
+ if (!CertStrToName(
+ X509_ASN_ENCODING,
+ const_cast<wchar_t*>(w_subject.c_str()),
+ CERT_X500_NAME_STR, NULL,
+ reinterpret_cast<BYTE*>(encoded_subject.get()),
+ &encoded_subject_length, NULL)) {
+ return NULL;
+ }
+
+ CERT_NAME_BLOB subject_name;
+ memset(&subject_name, 0, sizeof(subject_name));
+ subject_name.cbData = encoded_subject_length;
+ subject_name.pbData = reinterpret_cast<BYTE*>(encoded_subject.get());
+
+ CRYPT_ALGORITHM_IDENTIFIER sign_algo;
+ memset(&sign_algo, 0, sizeof(sign_algo));
+ sign_algo.pszObjId = szOID_RSA_SHA1RSA;
+
+ base::Time not_valid = base::Time::Now() + valid_duration;
+ base::Time::Exploded exploded;
+ not_valid.UTCExplode(&exploded);
+
+ // Create the system time struct representing our exploded time.
+ SYSTEMTIME system_time;
+ system_time.wYear = exploded.year;
+ system_time.wMonth = exploded.month;
+ system_time.wDayOfWeek = exploded.day_of_week;
+ system_time.wDay = exploded.day_of_month;
+ system_time.wHour = exploded.hour;
+ system_time.wMinute = exploded.minute;
+ system_time.wSecond = exploded.second;
+ system_time.wMilliseconds = exploded.millisecond;
+
+ PCCERT_CONTEXT cert_handle =
+ CertCreateSelfSignCertificate(key->provider(), &subject_name,
+ CERT_CREATE_SELFSIGN_NO_KEY_INFO,
+ NULL, &sign_algo, 0, &system_time, 0);
+ DCHECK(cert_handle) << "Failed to create self-signed certificate: "
+ << logging::GetLastSystemErrorCode();
+
+ X509Certificate* cert = CreateFromHandle(cert_handle,
+ SOURCE_LONE_CERT_IMPORT,
+ OSCertHandles());
+ FreeOSCertHandle(cert_handle);
+ return cert;
+}
+
void X509Certificate::Persist(Pickle* pickle) {
DCHECK(cert_handle_);
DWORD length;
@@ -529,7 +611,7 @@ class GlobalCertStore {
}
private:
- friend struct DefaultSingletonTraits<GlobalCertStore>;
+ friend struct base::DefaultLazyInstanceTraits<GlobalCertStore>;
GlobalCertStore()
: cert_store_(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)) {
@@ -544,9 +626,12 @@ class GlobalCertStore {
DISALLOW_COPY_AND_ASSIGN(GlobalCertStore);
};
+static base::LazyInstance<GlobalCertStore> g_cert_store(
+ base::LINKER_INITIALIZED);
+
// static
HCERTSTORE X509Certificate::cert_store() {
- return Singleton<GlobalCertStore>::get()->cert_store();
+ return g_cert_store.Get().cert_store();
}
int X509Certificate::Verify(const std::string& hostname,
@@ -606,15 +691,26 @@ int X509Certificate::Verify(const std::string& hostname,
}
}
+ // For non-test scenarios, use the default HCERTCHAINENGINE, NULL, which
+ // corresponds to HCCE_CURRENT_USER and is is initialized as needed by
+ // crypt32. However, when testing, it is necessary to create a new
+ // HCERTCHAINENGINE and use that instead. This is because each
+ // HCERTCHAINENGINE maintains a cache of information about certificates
+ // encountered, and each test run may modify the trust status of a
+ // certificate.
+ ScopedHCERTCHAINENGINE chain_engine(NULL);
+ if (TestRootCerts::HasInstance())
+ chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
+
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
// chain_flags argument.
if (!CertGetCertificateChain(
- NULL, // default chain engine, HCCE_CURRENT_USER
+ chain_engine,
cert_handle_,
NULL, // current system time
- cert_handle_->hCertStore, // search this store
+ cert_handle_->hCertStore,
&chain_para,
chain_flags,
NULL, // reserved
@@ -628,10 +724,10 @@ int X509Certificate::Verify(const std::string& hostname,
chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL;
CertFreeCertificateChain(chain_context);
if (!CertGetCertificateChain(
- NULL, // default chain engine, HCCE_CURRENT_USER
+ chain_engine,
cert_handle_,
NULL, // current system time
- cert_handle_->hCertStore, // search this store
+ cert_handle_->hCertStore,
&chain_para,
chain_flags,
NULL, // reserved
@@ -642,7 +738,6 @@ int X509Certificate::Verify(const std::string& hostname,
ScopedCertChainContext scoped_chain_context(chain_context);
GetCertChainInfo(chain_context, verify_result);
-
verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
chain_context->TrustStatus.dwErrorStatus);
@@ -748,6 +843,15 @@ int X509Certificate::Verify(const std::string& hostname,
return OK;
}
+bool X509Certificate::GetDEREncoded(std::string* encoded) {
+ if (!cert_handle_->pbCertEncoded || !cert_handle_->cbCertEncoded)
+ return false;
+ encoded->clear();
+ encoded->append(reinterpret_cast<char*>(cert_handle_->pbCertEncoded),
+ cert_handle_->cbCertEncoded);
+ return true;
+}
+
// Returns true if the certificate is an extended-validation certificate.
//
// This function checks the certificatePolicies extensions of the
diff --git a/net/base/x509_openssl_util.cc b/net/base/x509_openssl_util.cc
index 9e44c4b..35871ad 100644
--- a/net/base/x509_openssl_util.cc
+++ b/net/base/x509_openssl_util.cc
@@ -5,30 +5,14 @@
#include "net/base/x509_openssl_util.h"
#include "base/logging.h"
-#include "base/string_number_conversions.h"
#include "base/string_piece.h"
#include "base/string_util.h"
-#include "base/time.h"
+#include "net/base/x509_cert_types.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,
@@ -78,35 +62,10 @@ bool ParseDate(ASN1_TIME* x509_time, base::Time* time) {
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;
+ CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ?
+ CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
+ return ParseCertificateDate(str_date, format, time);
}
// TODO(joth): Investigate if we can upstream this into the OpenSSL library,
@@ -149,9 +108,17 @@ bool VerifyHostname(const std::string& hostname,
}
DCHECK(!reference_name.empty());
- // TODO(joth): Add IP address support. See http://crbug.com/62973
if (found_ip6_chars || !found_alpha) {
- NOTIMPLEMENTED() << hostname;
+ // For now we just do simple localhost IP address support, primarily as
+ // it's needed by the test server. TODO(joth): Replace this with full IP
+ // address support. See http://crbug.com/62973
+ if (hostname == "127.0.0.1" &&
+ std::find(cert_names.begin(), cert_names.end(), hostname) !=
+ cert_names.end()) {
+ DVLOG(1) << "Allowing localhost IP certificate: " << hostname;
+ return true;
+ }
+ NOTIMPLEMENTED() << hostname; // See comment above.
return false;
}
@@ -217,6 +184,6 @@ bool VerifyHostname(const std::string& hostname,
return false;
}
-} // namespace x509_openssl_util
+} // namespace x509_openssl_util
-} // namespace net
+} // namespace net
diff --git a/net/base/x509_openssl_util_unittest.cc b/net/base/x509_openssl_util_unittest.cc
index 50589ad..4727d4c 100644
--- a/net/base/x509_openssl_util_unittest.cc
+++ b/net/base/x509_openssl_util_unittest.cc
@@ -60,7 +60,8 @@ CertificateNameVerifyTestData kNameVerifyTestData[] = {
{ false, "baz2.example.net", "baz*.example.net" },
{ false, "bar.*.example.net", "bar.*.example.net" },
{ false, "bar.f*o.example.net", "bar.f*o.example.net" },
- // IP addresses currently not supported.
+ // IP addresses currently not supported, except for the localhost.
+ { true, "127.0.0.1", "127.0.0.1" },
{ false, "192.168.1.1", "192.168.1.1" },
{ false, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210",
"FEDC:BA98:7654:3210:FEDC:BA98:7654:3210" },
diff --git a/net/data/ftp/dir-listing-hprc-1 b/net/data/ftp/dir-listing-hprc-1
deleted file mode 100644
index ee3504f..0000000
--- a/net/data/ftp/dir-listing-hprc-1
+++ /dev/null
@@ -1,2 +0,0 @@
- .
- ..
diff --git a/net/data/ftp/dir-listing-hprc-1.expected b/net/data/ftp/dir-listing-hprc-1.expected
deleted file mode 100644
index 6259526..0000000
--- a/net/data/ftp/dir-listing-hprc-1.expected
+++ /dev/null
@@ -1,17 +0,0 @@
--
-.
-0
-1994
-11
-15
-12
-45
-
--
-..
-0
-1994
-11
-15
-12
-45
diff --git a/net/data/ftp/dir-listing-hprc-2 b/net/data/ftp/dir-listing-hprc-2
deleted file mode 100644
index 31a8688..0000000
--- a/net/data/ftp/dir-listing-hprc-2
+++ /dev/null
@@ -1,4 +0,0 @@
- .
- ..
- .welcome
- readme
diff --git a/net/data/ftp/dir-listing-hprc-2.expected b/net/data/ftp/dir-listing-hprc-2.expected
deleted file mode 100644
index e597b76..0000000
--- a/net/data/ftp/dir-listing-hprc-2.expected
+++ /dev/null
@@ -1,35 +0,0 @@
--
-.
-0
-1994
-11
-15
-12
-45
-
--
-..
-0
-1994
-11
-15
-12
-45
-
--
-.welcome
-0
-1994
-11
-15
-12
-45
-
--
-readme
-0
-1994
-11
-15
-12
-45
diff --git a/net/data/ftp/dir-listing-hprc-3 b/net/data/ftp/dir-listing-hprc-3
deleted file mode 100644
index 0e2f2d0..0000000
--- a/net/data/ftp/dir-listing-hprc-3
+++ /dev/null
@@ -1,3 +0,0 @@
- .
- ..
- Multi Word File Name.txt
diff --git a/net/data/ftp/dir-listing-hprc-3.expected b/net/data/ftp/dir-listing-hprc-3.expected
deleted file mode 100644
index a71cbd2..0000000
--- a/net/data/ftp/dir-listing-hprc-3.expected
+++ /dev/null
@@ -1,26 +0,0 @@
--
-.
-0
-1994
-11
-15
-12
-45
-
--
-..
-0
-1994
-11
-15
-12
-45
-
--
-Multi Word File Name.txt
-0
-1994
-11
-15
-12
-45
diff --git a/net/data/ftp/dir-listing-mlsd-1 b/net/data/ftp/dir-listing-mlsd-1
deleted file mode 100644
index 9463845..0000000
--- a/net/data/ftp/dir-listing-mlsd-1
+++ /dev/null
@@ -1,5 +0,0 @@
-type=dir;sizd=512;modify=20010414155043;UNIX.mode=0555;unique=6ag5b4e3ff; bin
-type=dir;sizd=512;modify=20010414155237;UNIX.mode=0555;unique=6ag5b4e400; etc
-type=dir;sizd=512;modify=20010705213550;UNIX.mode=0711;unique=6ag5b4e401; hidden
-type=dir;sizd=512;modify=20050422001005;UNIX.mode=0755;unique=100ff03g6164000; j
-type=dir;sizd=512;modify=20031021200128;UNIX.mode=0755;unique=6ag5b4e403; pub
diff --git a/net/data/ftp/dir-listing-mlsd-1.expected b/net/data/ftp/dir-listing-mlsd-1.expected
deleted file mode 100644
index 7720451..0000000
--- a/net/data/ftp/dir-listing-mlsd-1.expected
+++ /dev/null
@@ -1,44 +0,0 @@
-d
-bin
--1
-2001
-4
-14
-15
-50
-
-d
-etc
--1
-2001
-4
-14
-15
-52
-
-d
-hidden
--1
-2001
-7
-5
-21
-35
-
-d
-j
--1
-2005
-4
-22
-0
-10
-
-d
-pub
--1
-2003
-10
-21
-20
-1
diff --git a/net/data/ftp/dir-listing-mlsd-2 b/net/data/ftp/dir-listing-mlsd-2
deleted file mode 100644
index 939638a..0000000
--- a/net/data/ftp/dir-listing-mlsd-2
+++ /dev/null
@@ -1 +0,0 @@
-type=file;size=839;modify=19980908010757;UNIX.mode=0644;unique=6ag5b4e47d; ftpmotd
diff --git a/net/data/ftp/dir-listing-mlsd-2.expected b/net/data/ftp/dir-listing-mlsd-2.expected
deleted file mode 100644
index 33659ea..0000000
--- a/net/data/ftp/dir-listing-mlsd-2.expected
+++ /dev/null
@@ -1,8 +0,0 @@
--
-ftpmotd
-839
-1998
-9
-8
-1
-7
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index a58aaa1..1793476 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -34,3 +34,8 @@ unit tests.
- punycodetest.der : A test self-signed server certificate with punycode name.
The common name is "xn--wgv71a119e.com" (日本語.com)
+
+- unittest.selfsigned.der : A self-signed certificate generated using private
+ key in unittest.key.bin. The common name is "unittest".
+
+- unittest.key.bin : private key stored unencrypted.
diff --git a/net/data/ssl/certificates/unittest.key.bin b/net/data/ssl/certificates/unittest.key.bin
new file mode 100644
index 0000000..2ec712b
--- /dev/null
+++ b/net/data/ssl/certificates/unittest.key.bin
Binary files differ
diff --git a/net/data/ssl/certificates/unittest.selfsigned.der b/net/data/ssl/certificates/unittest.selfsigned.der
new file mode 100644
index 0000000..48c8d74
--- /dev/null
+++ b/net/data/ssl/certificates/unittest.selfsigned.der
Binary files differ
diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc
index 78ebcc0..284657f 100644
--- a/net/disk_cache/backend_impl.cc
+++ b/net/disk_cache/backend_impl.cc
@@ -179,7 +179,12 @@ bool SetFieldTrialInfo(int size_group) {
std::string group1 = base::StringPrintf("CacheSizeGroup_%d", size_group);
trial1->AppendGroup(group1, base::FieldTrial::kAllRemainingProbability);
- return false;
+ 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.
+
+ return trial2->group() == group2a;
}
// ------------------------------------------------------------------------
@@ -423,7 +428,7 @@ BackendImpl::~BackendImpl() {
// ------------------------------------------------------------------------
int32 BackendImpl::GetEntryCount() const {
- if (!index_)
+ if (!index_ || disabled_)
return 0;
// num_entries includes entries already evicted.
int32 not_deleted = data_->header.num_entries -
@@ -1214,6 +1219,10 @@ void BackendImpl::OnOperationCompleted(base::TimeDelta elapsed_time) {
if (cache_type() != net::DISK_CACHE)
return;
+ UMA_HISTOGRAM_TIMES(base::FieldTrial::MakeName("DiskCache.TotalIOTime",
+ "CacheThrottle").data(),
+ elapsed_time);
+
if (!throttle_requests_)
return;
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index bfb78b6..d3e79a1 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -1444,7 +1444,7 @@ void DiskCacheBackendTest::BackendDisable() {
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2));
- EXPECT_EQ(2, cache_->GetEntryCount());
+ EXPECT_EQ(0, cache_->GetEntryCount());
EXPECT_NE(net::OK, CreateEntry("Something new", &entry2));
entry1->Close();
@@ -1601,7 +1601,7 @@ void DiskCacheBackendTest::BackendDisable4() {
// This line should disable the cache but not delete it.
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry4));
- EXPECT_EQ(4, cache_->GetEntryCount());
+ EXPECT_EQ(0, cache_->GetEntryCount());
EXPECT_NE(net::OK, CreateEntry("cache is disabled", &entry4));
diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc
index ce59270..e5e6482 100644
--- a/net/disk_cache/entry_impl.cc
+++ b/net/disk_cache/entry_impl.cc
@@ -296,11 +296,15 @@ EntryImpl::EntryImpl(BackendImpl* backend, Addr address, bool read_only)
// written before).
EntryImpl::~EntryImpl() {
Log("~EntryImpl in");
- backend_->OnEntryDestroyBegin(entry_.address());
- // Save the sparse info to disk before deleting this entry.
+ // Save the sparse info to disk. This will generate IO for this entry and
+ // maybe for a child entry, so it is important to do it before deleting this
+ // entry.
sparse_.reset();
+ // Remove this entry from the list of open entries.
+ backend_->OnEntryDestroyBegin(entry_.address());
+
if (doomed_) {
DeleteEntryData(true);
} else {
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc
index bea940c..cb7f680 100644
--- a/net/disk_cache/entry_unittest.cc
+++ b/net/disk_cache/entry_unittest.cc
@@ -48,6 +48,7 @@ class DiskCacheEntryTest : public DiskCacheTestWithCache {
void HugeSparseIO();
void GetAvailableRange();
void CouldBeSparse();
+ void UpdateSparseEntry();
void DoomSparseEntry();
void PartialSparseEntry();
};
@@ -514,7 +515,7 @@ TEST_F(DiskCacheEntryTest, RequestThrottling) {
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.
+ // We have 9 queued requests, let's dispatch them all.
cache_impl_->ThrottleRequestsForTest(false);
EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
@@ -857,7 +858,7 @@ void DiskCacheEntryTest::ZeroLengthIO() {
EXPECT_EQ(0, ReadData(entry, 0, 50000, NULL, 0));
EXPECT_EQ(100000, entry->GetDataSize(0));
- // Lets verify the actual content.
+ // Let's verify the actual content.
const int kSize = 20;
const char zeros[kSize] = {};
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
@@ -1655,6 +1656,50 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyMisalignedGetAvailableRange) {
entry->Close();
}
+void DiskCacheEntryTest::UpdateSparseEntry() {
+ std::string key("the first key");
+ disk_cache::Entry* entry1;
+ ASSERT_EQ(net::OK, CreateEntry(key, &entry1));
+
+ const int kSize = 2048;
+ 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.
+ VerifySparseIO(entry1, 0, buf_1, kSize, buf_2);
+ entry1->Close();
+
+ // Write at offset 2048.
+ ASSERT_EQ(net::OK, OpenEntry(key, &entry1));
+ VerifySparseIO(entry1, 2048, buf_1, kSize, buf_2);
+
+ disk_cache::Entry* entry2;
+ ASSERT_EQ(net::OK, CreateEntry("the second key", &entry2));
+
+ entry1->Close();
+ entry2->Close();
+ FlushQueueForTest();
+ if (memory_only_)
+ EXPECT_EQ(2, cache_->GetEntryCount());
+ else
+ EXPECT_EQ(3, cache_->GetEntryCount());
+}
+
+TEST_F(DiskCacheEntryTest, UpdateSparseEntry) {
+ SetDirectMode();
+ SetCacheType(net::MEDIA_CACHE);
+ InitCache();
+ UpdateSparseEntry();
+}
+
+TEST_F(DiskCacheEntryTest, MemoryOnlyUpdateSparseEntry) {
+ SetMemoryOnlyMode();
+ SetCacheType(net::MEDIA_CACHE);
+ InitCache();
+ UpdateSparseEntry();
+}
+
void DiskCacheEntryTest::DoomSparseEntry() {
std::string key1("the first key");
std::string key2("the second key");
diff --git a/net/disk_cache/file_win.cc b/net/disk_cache/file_win.cc
index 5b01224..737b8e8 100644
--- a/net/disk_cache/file_win.cc
+++ b/net/disk_cache/file_win.cc
@@ -5,8 +5,8 @@
#include "net/disk_cache/file.h"
#include "base/file_path.h"
+#include "base/lazy_instance.h"
#include "base/message_loop.h"
-#include "base/singleton.h"
#include "net/disk_cache/disk_cache.h"
namespace {
@@ -33,6 +33,9 @@ class CompletionHandler : public MessageLoopForIO::IOHandler {
DWORD actual_bytes, DWORD error);
};
+static base::LazyInstance<CompletionHandler> g_completion_handler(
+ base::LINKER_INITIALIZED);
+
void CompletionHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
DWORD actual_bytes, DWORD error) {
MyOverlapped* data = reinterpret_cast<MyOverlapped*>(context);
@@ -52,7 +55,7 @@ void CompletionHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
MyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset,
disk_cache::FileIOCallback* callback) {
memset(this, 0, sizeof(*this));
- context_.handler = Singleton<CompletionHandler>::get();
+ context_.handler = g_completion_handler.Pointer();
context_.overlapped.Offset = static_cast<DWORD>(offset);
file_ = file;
callback_ = callback;
@@ -81,7 +84,7 @@ bool File::Init(const FilePath& name) {
return false;
MessageLoopForIO::current()->RegisterIOHandler(
- platform_file_, Singleton<CompletionHandler>::get());
+ platform_file_, g_completion_handler.Pointer());
init_ = true;
sync_platform_file_ = CreateFile(name.value().c_str(), access, sharing, NULL,
@@ -255,7 +258,7 @@ void File::WaitForPendingIO(int* num_pending_io) {
while (*num_pending_io) {
// Asynchronous IO operations may be in flight and the completion may end
// up calling us back so let's wait for them.
- MessageLoopForIO::IOHandler* handler = Singleton<CompletionHandler>::get();
+ MessageLoopForIO::IOHandler* handler = g_completion_handler.Pointer();
MessageLoopForIO::current()->WaitForIOCompletion(100, handler);
}
}
diff --git a/net/disk_cache/in_flight_backend_io.cc b/net/disk_cache/in_flight_backend_io.cc
index d83bd10..5752353 100644
--- a/net/disk_cache/in_flight_backend_io.cc
+++ b/net/disk_cache/in_flight_backend_io.cc
@@ -287,6 +287,7 @@ InFlightBackendIO::InFlightBackendIO(BackendImpl* backend,
base::MessageLoopProxy* background_thread)
: backend_(backend),
background_thread_(background_thread),
+ max_queue_len_(0),
queue_entry_ops_(false) {
}
@@ -445,10 +446,16 @@ void InFlightBackendIO::WaitForPendingIO() {
void InFlightBackendIO::StartQueingOperations() {
queue_entry_ops_ = true;
+ CACHE_UMA(COUNTS_10000, "InitialQueuedOperations", 0, pending_ops_.size());
+ if (!pending_ops_.size()) {
+ queueing_start_ = base::TimeTicks::Now();
+ max_queue_len_ = 0;
+ }
}
void InFlightBackendIO::StopQueingOperations() {
queue_entry_ops_ = false;
+ CACHE_UMA(COUNTS_10000, "FinalQueuedOperations", 0, pending_ops_.size());
}
void InFlightBackendIO::OnOperationComplete(BackgroundIO* operation,
@@ -461,13 +468,10 @@ void InFlightBackendIO::OnOperationComplete(BackgroundIO* operation,
// 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_ops_.size());
- PostAllQueuedOperations();
+ PostQueuedOperation();
+ if (!pending_ops_.size() && !queue_entry_ops_) {
+ CACHE_UMA(AGE_MS, "ThrottleTime", 0, queueing_start_);
+ CACHE_UMA(COUNTS_10000, "MaxQueuedOperations", 0, max_queue_len_);
}
}
}
@@ -498,6 +502,7 @@ void InFlightBackendIO::QueueOperation(BackendIO* operation) {
// We keep the operation that we are executing in the list so that we know
// when it completes.
pending_ops_.push_back(operation);
+ max_queue_len_ = std::max(max_queue_len_, pending_ops_.size());
if (empty_list)
PostOperation(operation);
}
@@ -517,14 +522,6 @@ void InFlightBackendIO::PostQueuedOperation() {
PostOperation(next_op);
}
-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();
diff --git a/net/disk_cache/in_flight_backend_io.h b/net/disk_cache/in_flight_backend_io.h
index ca239dd..7b4b111 100644
--- a/net/disk_cache/in_flight_backend_io.h
+++ b/net/disk_cache/in_flight_backend_io.h
@@ -200,12 +200,13 @@ class InFlightBackendIO : public InFlightIO {
void QueueOperation(BackendIO* operation);
void PostOperation(BackendIO* operation);
void PostQueuedOperation();
- void PostAllQueuedOperations();
bool RemoveFirstQueuedOperation(BackendIO* operation);
BackendImpl* backend_;
scoped_refptr<base::MessageLoopProxy> background_thread_;
OperationList pending_ops_; // Entry (async) operations to be posted.
+ base::TimeTicks queueing_start_;
+ size_t max_queue_len_;
bool queue_entry_ops_; // True if we are queuing entry (async) operations.
DISALLOW_COPY_AND_ASSIGN(InFlightBackendIO);
diff --git a/net/ftp/ftp_directory_listing_buffer.cc b/net/ftp/ftp_directory_listing_buffer.cc
index f6e8748..58533b8 100644
--- a/net/ftp/ftp_directory_listing_buffer.cc
+++ b/net/ftp/ftp_directory_listing_buffer.cc
@@ -9,9 +9,7 @@
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "net/base/net_errors.h"
-#include "net/ftp/ftp_directory_listing_parser_hprc.h"
#include "net/ftp/ftp_directory_listing_parser_ls.h"
-#include "net/ftp/ftp_directory_listing_parser_mlsd.h"
#include "net/ftp/ftp_directory_listing_parser_netware.h"
#include "net/ftp/ftp_directory_listing_parser_vms.h"
#include "net/ftp/ftp_directory_listing_parser_windows.h"
@@ -21,9 +19,7 @@ namespace net {
FtpDirectoryListingBuffer::FtpDirectoryListingBuffer(
const base::Time& current_time)
: current_parser_(NULL) {
- parsers_.insert(new FtpDirectoryListingParserHprc(current_time));
parsers_.insert(new FtpDirectoryListingParserLs(current_time));
- parsers_.insert(new FtpDirectoryListingParserMlsd());
parsers_.insert(new FtpDirectoryListingParserNetware(current_time));
parsers_.insert(new FtpDirectoryListingParserVms());
parsers_.insert(new FtpDirectoryListingParserWindows());
diff --git a/net/ftp/ftp_directory_listing_buffer_unittest.cc b/net/ftp/ftp_directory_listing_buffer_unittest.cc
index ceddfc4..cb120a6 100644
--- a/net/ftp/ftp_directory_listing_buffer_unittest.cc
+++ b/net/ftp/ftp_directory_listing_buffer_unittest.cc
@@ -19,9 +19,6 @@ namespace {
TEST(FtpDirectoryListingBufferTest, Parse) {
const char* test_files[] = {
- "dir-listing-hprc-1",
- "dir-listing-hprc-2",
- "dir-listing-hprc-3",
"dir-listing-ls-1",
"dir-listing-ls-1-utf8",
"dir-listing-ls-2",
@@ -45,8 +42,6 @@ TEST(FtpDirectoryListingBufferTest, Parse) {
"dir-listing-ls-20", // TODO(phajdan.jr): should use windows-1251 encoding.
"dir-listing-ls-21", // TODO(phajdan.jr): should use windows-1251 encoding.
"dir-listing-ls-22", // TODO(phajdan.jr): should use windows-1251 encoding.
- "dir-listing-mlsd-1",
- "dir-listing-mlsd-2",
"dir-listing-netware-1",
"dir-listing-netware-2",
"dir-listing-vms-1",
diff --git a/net/ftp/ftp_directory_listing_parser_hprc.cc b/net/ftp/ftp_directory_listing_parser_hprc.cc
deleted file mode 100644
index 621aba1..0000000
--- a/net/ftp/ftp_directory_listing_parser_hprc.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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/ftp/ftp_directory_listing_parser_hprc.h"
-
-#include "base/logging.h"
-#include "base/time.h"
-
-namespace net {
-
-FtpDirectoryListingParserHprc::FtpDirectoryListingParserHprc(
- const base::Time& current_time)
- : current_time_(current_time) {
-}
-
-FtpDirectoryListingParserHprc::~FtpDirectoryListingParserHprc() {}
-
-FtpServerType FtpDirectoryListingParserHprc::GetServerType() const {
- return SERVER_HPRC;
-}
-
-bool FtpDirectoryListingParserHprc::ConsumeLine(const string16& line) {
- if (line.empty())
- return false;
-
- // All lines begin with a space.
- if (line[0] != ' ')
- return false;
-
- FtpDirectoryListingEntry entry;
- entry.name = line.substr(1);
-
- // We don't know anything beyond the file name, so just pick some arbitrary
- // values.
- // TODO(phajdan.jr): consider adding an UNKNOWN entry type.
- entry.type = FtpDirectoryListingEntry::FILE;
- entry.size = 0;
- entry.last_modified = current_time_;
-
- entries_.push(entry);
- return true;
-}
-
-bool FtpDirectoryListingParserHprc::OnEndOfInput() {
- return true;
-}
-
-bool FtpDirectoryListingParserHprc::EntryAvailable() const {
- return !entries_.empty();
-}
-
-FtpDirectoryListingEntry FtpDirectoryListingParserHprc::PopEntry() {
- DCHECK(EntryAvailable());
- FtpDirectoryListingEntry entry = entries_.front();
- entries_.pop();
- return entry;
-}
-
-} // namespace net
diff --git a/net/ftp/ftp_directory_listing_parser_hprc.h b/net/ftp/ftp_directory_listing_parser_hprc.h
deleted file mode 100644
index d153810..0000000
--- a/net/ftp/ftp_directory_listing_parser_hprc.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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_FTP_FTP_DIRECTORY_LISTING_PARSER_HPRC_H_
-#define NET_FTP_FTP_DIRECTORY_LISTING_PARSER_HPRC_H_
-#pragma once
-
-#include <queue>
-
-#include "base/basictypes.h"
-#include "base/time.h"
-#include "net/ftp/ftp_directory_listing_parser.h"
-
-namespace net {
-
-// Parser for directory listings served by HPRC,
-// see http://hprc.external.hp.com/ and http://crbug.com/56547.
-class FtpDirectoryListingParserHprc : public FtpDirectoryListingParser {
- public:
- // Constructor. When we need to provide the last modification time
- // that we don't know, |current_time| will be used. This allows passing
- // a specific date during testing.
- explicit FtpDirectoryListingParserHprc(const base::Time& current_time);
- virtual ~FtpDirectoryListingParserHprc();
-
- // FtpDirectoryListingParser methods:
- virtual FtpServerType GetServerType() const;
- virtual bool ConsumeLine(const string16& line);
- virtual bool OnEndOfInput();
- virtual bool EntryAvailable() const;
- virtual FtpDirectoryListingEntry PopEntry();
-
- private:
- // Store the current time. We use it in place of last modification time
- // that is unknown (the server doesn't send it).
- const base::Time current_time_;
-
- std::queue<FtpDirectoryListingEntry> entries_;
-
- DISALLOW_COPY_AND_ASSIGN(FtpDirectoryListingParserHprc);
-};
-
-} // namespace net
-
-#endif // NET_FTP_FTP_DIRECTORY_LISTING_PARSER_HPRC_H_
diff --git a/net/ftp/ftp_directory_listing_parser_hprc_unittest.cc b/net/ftp/ftp_directory_listing_parser_hprc_unittest.cc
deleted file mode 100644
index bd057e9..0000000
--- a/net/ftp/ftp_directory_listing_parser_hprc_unittest.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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/ftp/ftp_directory_listing_parser_unittest.h"
-
-#include "base/format_macros.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "net/ftp/ftp_directory_listing_parser_hprc.h"
-
-namespace {
-
-typedef net::FtpDirectoryListingParserTest FtpDirectoryListingParserHprcTest;
-
-TEST_F(FtpDirectoryListingParserHprcTest, Good) {
- const struct SingleLineTestData good_cases[] = {
- { " .welcome",
- net::FtpDirectoryListingEntry::FILE, ".welcome", 0,
- 1994, 11, 15, 12, 45 },
- };
- for (size_t i = 0; i < arraysize(good_cases); i++) {
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
- good_cases[i].input));
-
- net::FtpDirectoryListingParserHprc parser(GetMockCurrentTime());
- RunSingleLineTestCase(&parser, good_cases[i]);
- }
-}
-
-TEST_F(FtpDirectoryListingParserHprcTest, Bad) {
- const char* bad_cases[] = {
- "",
- "test",
- "-rw-r--r-- 1 ftp ftp 528 Nov 01 2007 README",
- "d [RWCEAFMS] ftpadmin 512 Jan 29 2004 pub",
- "TEST.DIR;1 1 4-MAR-1999 22:14:34 [UCX$NOBO,ANONYMOUS] (RWE,RWE,RWE,RWE)",
- "type=dir;modify=20010414155237;UNIX.mode=0555;unique=6ag5b4e400; etc",
- };
- for (size_t i = 0; i < arraysize(bad_cases); i++) {
- net::FtpDirectoryListingParserHprc parser(GetMockCurrentTime());
- EXPECT_FALSE(parser.ConsumeLine(UTF8ToUTF16(bad_cases[i]))) << bad_cases[i];
- }
-}
-
-} // namespace
diff --git a/net/ftp/ftp_directory_listing_parser_ls.cc b/net/ftp/ftp_directory_listing_parser_ls.cc
index 40546c8..9660eab 100644
--- a/net/ftp/ftp_directory_listing_parser_ls.cc
+++ b/net/ftp/ftp_directory_listing_parser_ls.cc
@@ -91,6 +91,10 @@ FtpDirectoryListingParserLs::FtpDirectoryListingParserLs(
FtpDirectoryListingParserLs::~FtpDirectoryListingParserLs() {}
+FtpServerType FtpDirectoryListingParserLs::GetServerType() const {
+ return SERVER_LS;
+}
+
bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) {
if (line.empty() && !received_nonempty_line_) {
// Allow empty lines only at the beginning of the listing. For example VMS
diff --git a/net/ftp/ftp_directory_listing_parser_ls.h b/net/ftp/ftp_directory_listing_parser_ls.h
index 6cb3655..3004f70 100644
--- a/net/ftp/ftp_directory_listing_parser_ls.h
+++ b/net/ftp/ftp_directory_listing_parser_ls.h
@@ -23,7 +23,7 @@ class FtpDirectoryListingParserLs : public FtpDirectoryListingParser {
virtual ~FtpDirectoryListingParserLs();
// FtpDirectoryListingParser methods:
- virtual FtpServerType GetServerType() const { return SERVER_LS; }
+ virtual FtpServerType GetServerType() const;
virtual bool ConsumeLine(const string16& line);
virtual bool OnEndOfInput();
virtual bool EntryAvailable() const;
diff --git a/net/ftp/ftp_directory_listing_parser_mlsd.cc b/net/ftp/ftp_directory_listing_parser_mlsd.cc
deleted file mode 100644
index d8ae618..0000000
--- a/net/ftp/ftp_directory_listing_parser_mlsd.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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/ftp/ftp_directory_listing_parser_mlsd.h"
-
-#include <map>
-#include <vector>
-
-#include "base/stl_util-inl.h"
-#include "base/string_number_conversions.h"
-#include "base/string_split.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-
-// You can read the specification of the MLSD format at
-// http://tools.ietf.org/html/rfc3659#page-23.
-
-namespace {
-
-// The MLSD date listing is specified at
-// http://tools.ietf.org/html/rfc3659#page-6.
-bool MlsdDateListingToTime(const string16& text, base::Time* time) {
- base::Time::Exploded time_exploded = { 0 };
-
- // We will only test 12 characters, but RFC-3659 requires 14 (we ignore the
- // last two digits, which contain the number of seconds).
- if (text.length() < 14)
- return false;
-
- if (!base::StringToInt(text.begin(), text.begin() + 4, &time_exploded.year))
- return false;
- if (!base::StringToInt(text.begin() + 4,
- text.begin() + 6,
- &time_exploded.month))
- return false;
- if (!base::StringToInt(text.begin() + 6,
- text.begin() + 8,
- &time_exploded.day_of_month))
- return false;
- if (!base::StringToInt(text.begin() + 8,
- text.begin() + 10,
- &time_exploded.hour))
- return false;
- 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.
- *time = base::Time::FromLocalExploded(time_exploded);
- return true;
-}
-
-} // namespace
-
-namespace net {
-
-FtpDirectoryListingParserMlsd::FtpDirectoryListingParserMlsd() {}
-
-FtpDirectoryListingParserMlsd::~FtpDirectoryListingParserMlsd() {}
-
-bool FtpDirectoryListingParserMlsd::ConsumeLine(const string16& line) {
- // The first space indicates where the filename begins.
- string16::size_type first_space_pos = line.find(' ');
- if (first_space_pos == string16::npos || first_space_pos < 1)
- return false;
-
- string16 facts_string = line.substr(0, first_space_pos - 1);
- string16 filename = line.substr(first_space_pos + 1);
- std::vector<string16> facts_split;
- base::SplitString(facts_string, ';', &facts_split);
-
- const char* keys[] = {
- "modify",
- "size",
- "type",
- };
-
- std::map<std::string, string16> facts;
- for (std::vector<string16>::const_iterator i = facts_split.begin();
- i != facts_split.end(); ++i) {
- string16::size_type equal_sign_pos = i->find('=');
- if (equal_sign_pos == string16::npos)
- return false;
- string16 key = i->substr(0, equal_sign_pos);
- string16 value = i->substr(equal_sign_pos + 1);
-
- // If we're interested in a key, record its value. Note that we don't detect
- // a case when the server is sending duplicate keys. We're not validating
- // the input, just parsing it.
- for (size_t j = 0; j < arraysize(keys); j++)
- if (LowerCaseEqualsASCII(key, keys[j]))
- facts[keys[j]] = value;
- }
- if (!ContainsKey(facts, "type"))
- return false;
-
- FtpDirectoryListingEntry entry;
- entry.name = filename;
-
- if (LowerCaseEqualsASCII(facts["type"], "dir")) {
- entry.type = FtpDirectoryListingEntry::DIRECTORY;
- entry.size = -1;
- } else if (LowerCaseEqualsASCII(facts["type"], "file")) {
- entry.type = FtpDirectoryListingEntry::FILE;
- if (!ContainsKey(facts, "size"))
- return false;
- if (!base::StringToInt64(facts["size"], &entry.size))
- return false;
- } else {
- // Ignore other types of entries. They are either not interesting for us
- // (cdir, pdir), or not regular files (OS-specific types). There is no
- // specific type for symlink. Symlinks get a type of their target.
- return true;
- }
-
- if (!ContainsKey(facts, "modify"))
- return false;
- if (!MlsdDateListingToTime(facts["modify"], &entry.last_modified))
- return false;
-
- entries_.push(entry);
- return true;
-}
-
-bool FtpDirectoryListingParserMlsd::OnEndOfInput() {
- return true;
-}
-
-bool FtpDirectoryListingParserMlsd::EntryAvailable() const {
- return !entries_.empty();
-}
-
-FtpDirectoryListingEntry FtpDirectoryListingParserMlsd::PopEntry() {
- DCHECK(EntryAvailable());
- FtpDirectoryListingEntry entry = entries_.front();
- entries_.pop();
- return entry;
-}
-
-} // namespace net
diff --git a/net/ftp/ftp_directory_listing_parser_mlsd.h b/net/ftp/ftp_directory_listing_parser_mlsd.h
deleted file mode 100644
index c3e3acf..0000000
--- a/net/ftp/ftp_directory_listing_parser_mlsd.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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_FTP_FTP_DIRECTORY_LISTING_PARSER_MLSD_H_
-#define NET_FTP_FTP_DIRECTORY_LISTING_PARSER_MLSD_H_
-#pragma once
-
-#include <queue>
-
-#include "net/ftp/ftp_directory_listing_parser.h"
-
-namespace net {
-
-// Parser for MLSD directory listing (RFC-3659). For more info see
-// http://tools.ietf.org/html/rfc3659#page-23.
-class FtpDirectoryListingParserMlsd : public FtpDirectoryListingParser {
- public:
- FtpDirectoryListingParserMlsd();
- virtual ~FtpDirectoryListingParserMlsd();
-
- // FtpDirectoryListingParser methods:
- virtual FtpServerType GetServerType() const { return SERVER_MLSD; }
- virtual bool ConsumeLine(const string16& line);
- virtual bool OnEndOfInput();
- virtual bool EntryAvailable() const;
- virtual FtpDirectoryListingEntry PopEntry();
-
- private:
- std::queue<FtpDirectoryListingEntry> entries_;
-
- DISALLOW_COPY_AND_ASSIGN(FtpDirectoryListingParserMlsd);
-};
-
-} // namespace net
-
-#endif // NET_FTP_FTP_DIRECTORY_LISTING_PARSER_MLSD_H_
diff --git a/net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc b/net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc
deleted file mode 100644
index f65abc2..0000000
--- a/net/ftp/ftp_directory_listing_parser_mlsd_unittest.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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/ftp/ftp_directory_listing_parser_unittest.h"
-
-#include "base/format_macros.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "net/ftp/ftp_directory_listing_parser_mlsd.h"
-
-namespace {
-
-typedef net::FtpDirectoryListingParserTest FtpDirectoryListingParserMlsdTest;
-
-TEST_F(FtpDirectoryListingParserMlsdTest, Good) {
- const struct SingleLineTestData good_cases[] = {
- { "type=file;size=380565;modify=20030606190749; README",
- net::FtpDirectoryListingEntry::FILE, "README", 380565,
- 2003, 6, 6, 19, 7 },
- { "type=dir;sizd=512;modify=20031021200128; pub",
- net::FtpDirectoryListingEntry::DIRECTORY, "pub", -1,
- 2003, 10, 21, 20, 1 },
- { "type=dir;sizd=512;modify=20091009080706;UNIX.mode=0755; pub",
- net::FtpDirectoryListingEntry::DIRECTORY, "pub", -1,
- 2009, 10, 9, 8, 7 },
- { "type=dir;modify=20010414155237;UNIX.mode=0555;unique=6ag5b4e400; etc",
- net::FtpDirectoryListingEntry::DIRECTORY, "etc", -1,
- 2001, 4, 14, 15, 52 },
- };
- for (size_t i = 0; i < arraysize(good_cases); i++) {
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
- good_cases[i].input));
-
- net::FtpDirectoryListingParserMlsd parser;
- RunSingleLineTestCase(&parser, good_cases[i]);
- }
-}
-
-TEST_F(FtpDirectoryListingParserMlsdTest, Bad) {
- const char* bad_cases[] = {
- "",
- " ",
- " ",
- ";",
- "; ",
- " ;",
- " foo",
- "garbage",
- "total 5",
- "type=file;size=380565;modify=20030606190749;README",
- "type=file;size=380565;modify=20030606190749;",
- "type=file;size=380565;modify=20030606190749",
- "size=380565;modify=20030606190749; README",
- "type=file;modify=20030606190749; README",
- "type=file;size=380565; README",
- "type=file; size=380565; modify=20030606190749; README",
- " type=file;size=380565;modify=20030606190749; README",
- "type=file;size=garbage;modify=20030606190749; README",
- "type=file;size=380565;modify=garbage; README",
- };
- for (size_t i = 0; i < arraysize(bad_cases); i++) {
- net::FtpDirectoryListingParserMlsd parser;
- EXPECT_FALSE(parser.ConsumeLine(UTF8ToUTF16(bad_cases[i]))) << bad_cases[i];
- }
-}
-
-} // namespace
diff --git a/net/ftp/ftp_directory_listing_parser_netware.cc b/net/ftp/ftp_directory_listing_parser_netware.cc
index ab7fb6d..1801a4a 100644
--- a/net/ftp/ftp_directory_listing_parser_netware.cc
+++ b/net/ftp/ftp_directory_listing_parser_netware.cc
@@ -42,6 +42,10 @@ FtpDirectoryListingParserNetware::FtpDirectoryListingParserNetware(
FtpDirectoryListingParserNetware::~FtpDirectoryListingParserNetware() {}
+FtpServerType FtpDirectoryListingParserNetware::GetServerType() const {
+ return SERVER_NETWARE;
+}
+
bool FtpDirectoryListingParserNetware::ConsumeLine(const string16& line) {
if (!received_first_line_) {
received_first_line_ = true;
diff --git a/net/ftp/ftp_directory_listing_parser_netware.h b/net/ftp/ftp_directory_listing_parser_netware.h
index 5fdcd84..48aebfc 100644
--- a/net/ftp/ftp_directory_listing_parser_netware.h
+++ b/net/ftp/ftp_directory_listing_parser_netware.h
@@ -23,7 +23,7 @@ class FtpDirectoryListingParserNetware : public FtpDirectoryListingParser {
virtual ~FtpDirectoryListingParserNetware();
// FtpDirectoryListingParser methods:
- virtual FtpServerType GetServerType() const { return SERVER_NETWARE; }
+ virtual FtpServerType GetServerType() const;
virtual bool ConsumeLine(const string16& line);
virtual bool OnEndOfInput();
virtual bool EntryAvailable() const;
diff --git a/net/ftp/ftp_directory_listing_parser_vms.cc b/net/ftp/ftp_directory_listing_parser_vms.cc
index ed12665..c74dad0 100644
--- a/net/ftp/ftp_directory_listing_parser_vms.cc
+++ b/net/ftp/ftp_directory_listing_parser_vms.cc
@@ -170,6 +170,10 @@ FtpDirectoryListingParserVms::FtpDirectoryListingParserVms()
FtpDirectoryListingParserVms::~FtpDirectoryListingParserVms() {}
+FtpServerType FtpDirectoryListingParserVms::GetServerType() const {
+ return SERVER_VMS;
+}
+
bool FtpDirectoryListingParserVms::ConsumeLine(const string16& line) {
switch (state_) {
case STATE_INITIAL:
diff --git a/net/ftp/ftp_directory_listing_parser_vms.h b/net/ftp/ftp_directory_listing_parser_vms.h
index 12f8dc7..118365d 100644
--- a/net/ftp/ftp_directory_listing_parser_vms.h
+++ b/net/ftp/ftp_directory_listing_parser_vms.h
@@ -19,7 +19,7 @@ class FtpDirectoryListingParserVms : public FtpDirectoryListingParser {
virtual ~FtpDirectoryListingParserVms();
// FtpDirectoryListingParser methods:
- virtual FtpServerType GetServerType() const { return SERVER_VMS; }
+ virtual FtpServerType GetServerType() const;
virtual bool ConsumeLine(const string16& line);
virtual bool OnEndOfInput();
virtual bool EntryAvailable() const;
diff --git a/net/ftp/ftp_directory_listing_parser_windows.cc b/net/ftp/ftp_directory_listing_parser_windows.cc
index e321173..ef733d5 100644
--- a/net/ftp/ftp_directory_listing_parser_windows.cc
+++ b/net/ftp/ftp_directory_listing_parser_windows.cc
@@ -15,7 +15,7 @@ namespace {
bool WindowsDateListingToTime(const std::vector<string16>& columns,
base::Time* time) {
- DCHECK_LE(4U, columns.size());
+ DCHECK_LE(3U, columns.size());
base::Time::Exploded time_exploded = { 0 };
@@ -76,19 +76,26 @@ FtpDirectoryListingParserWindows::FtpDirectoryListingParserWindows() {}
FtpDirectoryListingParserWindows::~FtpDirectoryListingParserWindows() {}
+FtpServerType FtpDirectoryListingParserWindows::GetServerType() const {
+ return SERVER_WINDOWS;
+}
+
bool FtpDirectoryListingParserWindows::ConsumeLine(const string16& line) {
std::vector<string16> columns;
base::SplitString(CollapseWhitespace(line, false), ' ', &columns);
- // 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() < 4)
+ // Every line of the listing consists of the following:
+ //
+ // 1. date
+ // 2. time
+ // 3. size in bytes (or "<DIR>" for directories)
+ // 4. filename (may be empty or contain spaces)
+ //
+ // For now, make sure we have 1-3, and handle 4 later.
+ if (columns.size() < 3)
return false;
FtpDirectoryListingEntry entry;
- entry.name = FtpUtil::GetStringPartAfterColumns(line, 3);
-
if (EqualsASCII(columns[2], "<DIR>")) {
entry.type = FtpDirectoryListingEntry::DIRECTORY;
entry.size = -1;
@@ -103,6 +110,14 @@ bool FtpDirectoryListingParserWindows::ConsumeLine(const string16& line) {
if (!WindowsDateListingToTime(columns, &entry.last_modified))
return false;
+ entry.name = FtpUtil::GetStringPartAfterColumns(line, 3);
+ 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;
+ }
+
entries_.push(entry);
return true;
}
diff --git a/net/ftp/ftp_directory_listing_parser_windows.h b/net/ftp/ftp_directory_listing_parser_windows.h
index 91ffe36..1f029af 100644
--- a/net/ftp/ftp_directory_listing_parser_windows.h
+++ b/net/ftp/ftp_directory_listing_parser_windows.h
@@ -18,7 +18,7 @@ class FtpDirectoryListingParserWindows : public FtpDirectoryListingParser {
virtual ~FtpDirectoryListingParserWindows();
// FtpDirectoryListingParser methods:
- virtual FtpServerType GetServerType() const { return SERVER_WINDOWS; }
+ virtual FtpServerType GetServerType() const;
virtual bool ConsumeLine(const string16& line);
virtual bool OnEndOfInput();
virtual bool EntryAvailable() const;
diff --git a/net/ftp/ftp_directory_listing_parser_windows_unittest.cc b/net/ftp/ftp_directory_listing_parser_windows_unittest.cc
index 60309cb..aeb64e7 100644
--- a/net/ftp/ftp_directory_listing_parser_windows_unittest.cc
+++ b/net/ftp/ftp_directory_listing_parser_windows_unittest.cc
@@ -64,15 +64,42 @@ TEST_F(FtpDirectoryListingParserWindowsTest, Good) {
}
}
+TEST_F(FtpDirectoryListingParserWindowsTest, Ignored) {
+ const char* ignored_cases[] = {
+ "12-07-10 12:05AM <DIR> ", // http://crbug.com/66097
+ "12-07-10 12:05AM 1234 ",
+ };
+ for (size_t i = 0; i < arraysize(ignored_cases); i++) {
+ SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
+ ignored_cases[i]));
+
+ net::FtpDirectoryListingParserWindows parser;
+ EXPECT_TRUE(parser.ConsumeLine(UTF8ToUTF16(ignored_cases[i])));
+ EXPECT_FALSE(parser.EntryAvailable());
+ EXPECT_TRUE(parser.OnEndOfInput());
+ EXPECT_FALSE(parser.EntryAvailable());
+ }
+}
+
TEST_F(FtpDirectoryListingParserWindowsTest, Bad) {
const char* bad_cases[] = {
"",
"garbage",
+ "11-02-09 05:32PM <GARBAGE>",
"11-02-09 05:32PM <GARBAGE> NT",
+ "11-02-09 05:32 <DIR>",
+ "11-FEB-09 05:32PM <DIR>",
+ "11-02 05:32PM <DIR>",
+ "11-02-09 05:32PM -1",
"11-02-09 05:32 <DIR> NT",
"11-FEB-09 05:32PM <DIR> NT",
"11-02 05:32PM <DIR> NT",
"11-02-09 05:32PM -1 NT",
+ "99-25-10 12:00AM 0",
+ "12-99-10 12:00AM 0",
+ "12-25-10 99:00AM 0",
+ "12-25-10 12:99AM 0",
+ "12-25-10 12:00ZM 0",
"99-25-10 12:00AM 0 months out of range",
"12-99-10 12:00AM 0 days out of range",
"12-25-10 99:00AM 0 hours out of range",
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index bfda5bd..0285e08 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -371,9 +371,6 @@ int FtpNetworkTransaction::ProcessCtrlResponse() {
case COMMAND_CWD:
rv = ProcessResponseCWD(response);
break;
- case COMMAND_MLSD:
- rv = ProcessResponseMLSD(response);
- break;
case COMMAND_LIST:
rv = ProcessResponseLIST(response);
break;
@@ -394,9 +391,6 @@ int FtpNetworkTransaction::ProcessCtrlResponse() {
case COMMAND_RETR:
rv = ProcessResponseRETR(response);
break;
- case COMMAND_MLSD:
- rv = ProcessResponseMLSD(response);
- break;
case COMMAND_LIST:
rv = ProcessResponseLIST(response);
break;
@@ -573,10 +567,6 @@ int FtpNetworkTransaction::DoLoop(int result) {
DCHECK(rv == OK);
rv = DoCtrlWriteCWD();
break;
- case STATE_CTRL_WRITE_MLSD:
- DCHECK(rv == 0);
- rv = DoCtrlWriteMLSD();
- break;
case STATE_CTRL_WRITE_LIST:
DCHECK(rv == OK);
rv = DoCtrlWriteLIST();
@@ -1073,7 +1063,7 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
case ERROR_CLASS_INITIATED:
return Stop(ERR_INVALID_RESPONSE);
case ERROR_CLASS_OK:
- next_state_ = STATE_CTRL_WRITE_MLSD;
+ next_state_ = STATE_CTRL_WRITE_LIST;
break;
case ERROR_CLASS_INFO_NEEDED:
return Stop(ERR_INVALID_RESPONSE);
@@ -1104,41 +1094,6 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
return OK;
}
-// MLSD command
-int FtpNetworkTransaction::DoCtrlWriteMLSD() {
- next_state_ = STATE_CTRL_READ;
- return SendFtpCommand("MLSD", COMMAND_MLSD);
-}
-
-int FtpNetworkTransaction::ProcessResponseMLSD(
- const FtpCtrlResponse& response) {
- switch (GetErrorClass(response.status_code)) {
- case ERROR_CLASS_INITIATED:
- // We want the client to start reading the response at this point.
- // It got here either through Start or RestartWithAuth. We want that
- // method to complete. Not setting next state here will make DoLoop exit
- // and in turn make Start/RestartWithAuth complete.
- response_.is_directory_listing = true;
- break;
- case ERROR_CLASS_OK:
- response_.is_directory_listing = true;
- next_state_ = STATE_CTRL_WRITE_QUIT;
- break;
- case ERROR_CLASS_INFO_NEEDED:
- return Stop(ERR_INVALID_RESPONSE);
- case ERROR_CLASS_TRANSIENT_ERROR:
- case ERROR_CLASS_PERMANENT_ERROR:
- // Fallback to the LIST command, more widely supported,
- // but without a specified output format.
- next_state_ = STATE_CTRL_WRITE_LIST;
- break;
- default:
- NOTREACHED();
- return Stop(ERR_UNEXPECTED);
- }
- return OK;
-}
-
// LIST command
int FtpNetworkTransaction::DoCtrlWriteLIST() {
std::string command(system_type_ == SYSTEM_TYPE_VMS ? "LIST *.*;0" : "LIST");
diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h
index 5bad335..678308a 100644
--- a/net/ftp/ftp_network_transaction.h
+++ b/net/ftp/ftp_network_transaction.h
@@ -58,7 +58,6 @@ class FtpNetworkTransaction : public FtpTransaction {
COMMAND_SIZE,
COMMAND_RETR,
COMMAND_CWD,
- COMMAND_MLSD,
COMMAND_LIST,
COMMAND_QUIT,
};
@@ -142,8 +141,6 @@ class FtpNetworkTransaction : public FtpTransaction {
int ProcessResponseSIZE(const FtpCtrlResponse& response);
int DoCtrlWriteCWD();
int ProcessResponseCWD(const FtpCtrlResponse& response);
- int DoCtrlWriteMLSD();
- int ProcessResponseMLSD(const FtpCtrlResponse& response);
int DoCtrlWriteLIST();
int ProcessResponseLIST(const FtpCtrlResponse& response);
int DoCtrlWriteQUIT();
@@ -234,7 +231,6 @@ class FtpNetworkTransaction : public FtpTransaction {
STATE_CTRL_WRITE_RETR,
STATE_CTRL_WRITE_SIZE,
STATE_CTRL_WRITE_CWD,
- STATE_CTRL_WRITE_MLSD,
STATE_CTRL_WRITE_LIST,
STATE_CTRL_WRITE_QUIT,
// Data connection states:
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index 1c22c5b..8da3baf 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -41,7 +41,6 @@ class FtpSocketDataProvider : public DynamicSocketDataProvider {
PRE_SIZE,
PRE_EPSV,
PRE_PASV,
- PRE_MLSD,
PRE_LIST,
PRE_RETR,
PRE_CWD,
@@ -189,11 +188,7 @@ class FtpSocketDataProviderDirectoryListing : public FtpSocketDataProvider {
return Verify("SIZE /\r\n", data, PRE_CWD,
"550 I can only retrieve regular files\r\n");
case PRE_CWD:
- return Verify("CWD /\r\n", data, PRE_MLSD, "200 OK\r\n");
- case PRE_MLSD:
- return Verify("MLSD\r\n", data, PRE_QUIT,
- "150 Accepted data connection\r\n"
- "226 MLSD complete\r\n");
+ return Verify("CWD /\r\n", data, PRE_LIST, "200 OK\r\n");
case PRE_LIST:
return Verify("LIST\r\n", data, PRE_QUIT, "200 OK\r\n");
default:
@@ -275,10 +270,8 @@ class FtpSocketDataProviderVMSDirectoryListing : public FtpSocketDataProvider {
return Verify("SIZE ANONYMOUS_ROOT:[000000]dir\r\n", data, PRE_CWD,
"550 I can only retrieve regular files\r\n");
case PRE_CWD:
- return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data, PRE_MLSD,
+ return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data, PRE_LIST,
"200 OK\r\n");
- case PRE_MLSD:
- return Verify("MLSD\r\n", data, PRE_LIST, "500 Invalid command\r\n");
case PRE_LIST:
return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
default:
@@ -315,10 +308,8 @@ class FtpSocketDataProviderVMSDirectoryListingRootDirectory
return Verify("SIZE ANONYMOUS_ROOT\r\n", data, PRE_CWD,
"550 I can only retrieve regular files\r\n");
case PRE_CWD:
- return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data, PRE_MLSD,
+ return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data, PRE_LIST,
"200 OK\r\n");
- case PRE_MLSD:
- return Verify("MLSD\r\n", data, PRE_LIST, "500 Invalid command\r\n");
case PRE_LIST:
return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
default:
@@ -1329,16 +1320,6 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) {
ERR_FTP_FAILED);
}
-TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailMlsd) {
- FtpSocketDataProviderDirectoryListing ctrl_socket;
- TransactionFailHelper(&ctrl_socket,
- "ftp://host",
- FtpSocketDataProvider::PRE_MLSD,
- FtpSocketDataProvider::PRE_LIST,
- "500 Unrecognized command\r\n",
- OK);
-}
-
TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
// Use unallocated 599 FTP error code to make sure it falls into the generic
diff --git a/net/ftp/ftp_server_type_histograms.h b/net/ftp/ftp_server_type_histograms.h
index 6a856b1..e89ad3d 100644
--- a/net/ftp/ftp_server_type_histograms.h
+++ b/net/ftp/ftp_server_type_histograms.h
@@ -24,8 +24,8 @@ enum FtpServerType {
SERVER_WINDOWS = 10, // Server using Windows listing style.
SERVER_VMS = 11, // Server using VMS listing style.
SERVER_NETWARE = 12, // Server using Netware listing style.
- SERVER_MLSD = 13, // Server using MLSD listing (RFC-3659).
- SERVER_HPRC = 14, // Server using HPRC listing (http://crbug.com/56547).
+
+ // Types 13-14 are RESERVED (were earlier used for MLSD listings).
NUM_OF_SERVER_TYPES
};
diff --git a/net/http/des.cc b/net/http/des.cc
index 21a8455..2a5ffa0 100644
--- a/net/http/des.cc
+++ b/net/http/des.cc
@@ -6,7 +6,10 @@
#include "base/logging.h"
-#if defined(USE_NSS)
+#if defined(USE_OPENSSL)
+#include <openssl/des.h>
+#include "base/openssl_util.h"
+#elif defined(USE_NSS)
#include <nss.h>
#include <pk11pub.h>
#include "base/nss_util.h"
@@ -92,10 +95,15 @@ void DESMakeKey(const uint8* raw, uint8* key) {
#if defined(USE_OPENSSL)
void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
+<<<<<<< HEAD
#ifndef ANDROID
base::EnsureOpenSSLInit();
#endif
+=======
+ base::EnsureOpenSSLInit();
+
+>>>>>>> chromium.org at r10.0.621.0
DES_key_schedule ks;
DES_set_key_unchecked(
reinterpret_cast<const_DES_cblock*>(const_cast<uint8*>(key)), &ks);
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc
index cd1cac8..1b1dfaf 100644
--- a/net/http/disk_cache_based_ssl_host_info.cc
+++ b/net/http/disk_cache_based_ssl_host_info.cc
@@ -9,6 +9,7 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_cache.h"
+#include "net/http/http_network_session.h"
namespace net {
@@ -16,10 +17,11 @@ DiskCacheBasedSSLHostInfo::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)),
+ : SSLHostInfo(hostname, ssl_config,
+ http_cache->network_layer()->GetSession()->cert_verifier()),
+ weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ callback_(new CallbackImpl(weak_ptr_factory_.GetWeakPtr(),
+ &DiskCacheBasedSSLHostInfo::DoLoop)),
state_(GET_BACKEND),
ready_(false),
hostname_(hostname),
@@ -39,7 +41,8 @@ DiskCacheBasedSSLHostInfo::~DiskCacheBasedSSLHostInfo() {
DCHECK(!user_callback_);
if (entry_)
entry_->Close();
- callback_->Cancel();
+ if (!IsCallbackPending())
+ delete callback_;
}
std::string DiskCacheBasedSSLHostInfo::key() const {
@@ -92,13 +95,27 @@ void DiskCacheBasedSSLHostInfo::DoLoop(int rv) {
} while (rv != ERR_IO_PENDING && state_ != NONE);
}
+bool DiskCacheBasedSSLHostInfo::IsCallbackPending() const {
+ switch (state_) {
+ case GET_BACKEND_COMPLETE:
+ case OPEN_COMPLETE:
+ case READ_COMPLETE:
+ case CREATE_COMPLETE:
+ case WRITE_COMPLETE:
+ return true;
+ default:
+ return false;
+ }
+}
+
int DiskCacheBasedSSLHostInfo::DoGetBackend() {
state_ = GET_BACKEND_COMPLETE;
- return http_cache_->GetBackend(&backend_, callback_.get());
+ return http_cache_->GetBackend(callback_->backend_pointer(), callback_);
}
int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) {
if (rv == OK) {
+ backend_ = callback_->backend();
state_ = OPEN;
} else {
state_ = WAIT_FOR_DATA_READY_DONE;
@@ -108,11 +125,12 @@ int DiskCacheBasedSSLHostInfo::DoGetBackendComplete(int rv) {
int DiskCacheBasedSSLHostInfo::DoOpen() {
state_ = OPEN_COMPLETE;
- return backend_->OpenEntry(key(), &entry_, callback_.get());
+ return backend_->OpenEntry(key(), callback_->entry_pointer(), callback_);
}
int DiskCacheBasedSSLHostInfo::DoOpenComplete(int rv) {
if (rv == OK) {
+ entry_ = callback_->entry();
state_ = READ;
} else {
state_ = WAIT_FOR_DATA_READY_DONE;
@@ -131,7 +149,7 @@ int DiskCacheBasedSSLHostInfo::DoRead() {
read_buffer_ = new IOBuffer(size);
state_ = READ_COMPLETE;
return entry_->ReadData(0 /* index */, 0 /* offset */, read_buffer_,
- size, callback_.get());
+ size, callback_);
}
int DiskCacheBasedSSLHostInfo::DoReadComplete(int rv) {
@@ -195,13 +213,14 @@ void DiskCacheBasedSSLHostInfo::Persist() {
int DiskCacheBasedSSLHostInfo::DoCreate() {
DCHECK(entry_ == NULL);
state_ = CREATE_COMPLETE;
- return backend_->CreateEntry(key(), &entry_, callback_.get());
+ return backend_->CreateEntry(key(), callback_->entry_pointer(), callback_);
}
int DiskCacheBasedSSLHostInfo::DoCreateComplete(int rv) {
if (rv != OK) {
state_ = SET_DONE;
} else {
+ entry_ = callback_->entry();
state_ = WRITE;
}
return OK;
@@ -211,9 +230,9 @@ int DiskCacheBasedSSLHostInfo::DoWrite() {
write_buffer_ = new IOBuffer(new_data_.size());
memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
state_ = WRITE_COMPLETE;
+
return entry_->WriteData(0 /* index */, 0 /* offset */, write_buffer_,
- new_data_.size(), callback_.get(),
- true /* truncate */);
+ new_data_.size(), callback_, true /* truncate */);
}
int DiskCacheBasedSSLHostInfo::DoWriteComplete(int rv) {
diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h
index 1d53b90..fee0a5c 100644
--- a/net/http/disk_cache_based_ssl_host_info.h
+++ b/net/http/disk_cache_based_ssl_host_info.h
@@ -10,6 +10,7 @@
#include "base/lock.h"
#include "base/non_thread_safe.h"
#include "base/scoped_ptr.h"
+#include "base/weak_ptr.h"
#include "net/base/completion_callback.h"
#include "net/disk_cache/disk_cache.h"
#include "net/socket/ssl_host_info.h"
@@ -36,7 +37,53 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
virtual void Persist();
private:
+ enum State {
+ GET_BACKEND,
+ GET_BACKEND_COMPLETE,
+ OPEN,
+ OPEN_COMPLETE,
+ READ,
+ READ_COMPLETE,
+ WAIT_FOR_DATA_READY_DONE,
+ CREATE,
+ CREATE_COMPLETE,
+ WRITE,
+ WRITE_COMPLETE,
+ SET_DONE,
+ NONE,
+ };
+
~DiskCacheBasedSSLHostInfo();
+
+ class CallbackImpl : public CallbackRunner<Tuple1<int> > {
+ public:
+ CallbackImpl(const base::WeakPtr<DiskCacheBasedSSLHostInfo>& obj,
+ void (DiskCacheBasedSSLHostInfo::*meth) (int))
+ : obj_(obj),
+ meth_(meth) {
+ }
+
+ virtual void RunWithParams(const Tuple1<int>& params) {
+ if (!obj_) {
+ delete this;
+ } else {
+ DispatchToMethod(obj_.get(), meth_, params);
+ }
+ }
+
+ disk_cache::Backend** backend_pointer() { return &backend_; }
+ disk_cache::Entry** entry_pointer() { return &entry_; }
+ disk_cache::Backend* backend() const { return backend_; }
+ disk_cache::Entry* entry() const { return entry_; }
+
+ private:
+ base::WeakPtr<DiskCacheBasedSSLHostInfo> obj_;
+ void (DiskCacheBasedSSLHostInfo::*meth_) (int);
+
+ disk_cache::Backend* backend_;
+ disk_cache::Entry* entry_;
+ };
+
std::string key() const;
void DoLoop(int rv);
@@ -58,31 +105,18 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
// SetDone is the terminal state of the write operation.
int SetDone();
- enum State {
- GET_BACKEND,
- GET_BACKEND_COMPLETE,
- OPEN,
- OPEN_COMPLETE,
- READ,
- READ_COMPLETE,
- WAIT_FOR_DATA_READY_DONE,
- CREATE,
- CREATE_COMPLETE,
- WRITE,
- WRITE_COMPLETE,
- SET_DONE,
- NONE,
- };
+ // IsCallbackPending returns true if we have a pending callback.
+ bool IsCallbackPending() const;
- scoped_refptr<CancelableCompletionCallback<DiskCacheBasedSSLHostInfo> >
- callback_;
+ base::WeakPtrFactory<DiskCacheBasedSSLHostInfo> weak_ptr_factory_;
+ CallbackImpl* callback_;
State state_;
bool ready_;
std::string new_data_;
const std::string hostname_;
HttpCache* const http_cache_;
disk_cache::Backend* backend_;
- disk_cache::Entry *entry_;
+ disk_cache::Entry* entry_;
CompletionCallback* user_callback_;
scoped_refptr<net::IOBuffer> read_buffer_;
scoped_refptr<net::IOBuffer> write_buffer_;
diff --git a/net/http/http_alternate_protocols.h b/net/http/http_alternate_protocols.h
index e06e13a..d5f9d77 100644
--- a/net/http/http_alternate_protocols.h
+++ b/net/http/http_alternate_protocols.h
@@ -26,6 +26,7 @@ class HttpAlternateProtocols {
NPN_SPDY_2,
NUM_ALTERNATE_PROTOCOLS,
BROKEN, // The alternate protocol is known to be broken.
+ UNINITIALIZED,
};
struct PortProtocolPair {
diff --git a/net/http/http_auth_cache_unittest.cc b/net/http/http_auth_cache_unittest.cc
index 5773d15..2c28969 100644
--- a/net/http/http_auth_cache_unittest.cc
+++ b/net/http/http_auth_cache_unittest.cc
@@ -29,7 +29,7 @@ class MockAuthHandler : public HttpAuthHandler {
properties_ = 0;
}
- HttpAuth::AuthorizationResult HandleAnotherChallenge(
+ virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
HttpAuth::ChallengeTokenizer* challenge) {
return HttpAuth::AUTHORIZATION_RESULT_REJECT;
}
diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc
index e4e2dd4..e97d06e 100644
--- a/net/http/http_auth_controller.cc
+++ b/net/http/http_auth_controller.cc
@@ -52,10 +52,36 @@ std::string AuthChallengeLogMessage(HttpResponseHeaders* headers) {
enum AuthEvent {
AUTH_EVENT_START = 0,
- AUTH_EVENT_REJECT = 1,
- AUTH_EVENT_MAX = 2,
+ AUTH_EVENT_REJECT,
+ AUTH_EVENT_MAX,
};
+enum AuthTarget {
+ AUTH_TARGET_PROXY = 0,
+ AUTH_TARGET_SECURE_PROXY,
+ AUTH_TARGET_SERVER,
+ AUTH_TARGET_SECURE_SERVER,
+ AUTH_TARGET_MAX,
+};
+
+AuthTarget DetermineAuthTarget(const HttpAuthHandler* handler) {
+ switch (handler->target()) {
+ case HttpAuth::AUTH_PROXY:
+ if (handler->origin().SchemeIsSecure())
+ return AUTH_TARGET_SECURE_PROXY;
+ else
+ return AUTH_TARGET_PROXY;
+ case HttpAuth::AUTH_SERVER:
+ if (handler->origin().SchemeIsSecure())
+ return AUTH_TARGET_SECURE_SERVER;
+ else
+ return AUTH_TARGET_SERVER;
+ default:
+ NOTREACHED();
+ return AUTH_TARGET_MAX;
+ }
+}
+
// Records the number of authentication events per authentication scheme.
void HistogramAuthEvent(HttpAuthHandler* handler, AuthEvent auth_event) {
#if !defined(NDEBUG)
@@ -68,8 +94,12 @@ void HistogramAuthEvent(HttpAuthHandler* handler, AuthEvent auth_event) {
DCHECK_EQ(first_thread, PlatformThread::CurrentId());
#endif
- // This assumes that the schemes maintain a consistent score from
- // 1 to 4 inclusive. The results map to:
+ HttpAuthHandler::AuthScheme auth_scheme = handler->auth_scheme();
+ DCHECK(auth_scheme >= 0 && auth_scheme < HttpAuthHandler::AUTH_SCHEME_MAX);
+
+ // Record start and rejection events for authentication.
+ //
+ // The results map to:
// Basic Start: 0
// Basic Reject: 1
// Digest Start: 2
@@ -78,12 +108,41 @@ void HistogramAuthEvent(HttpAuthHandler* handler, AuthEvent auth_event) {
// NTLM Reject: 5
// Negotiate Start: 6
// Negotiate Reject: 7
- static const int kScoreMin = 1;
- static const int kScoreMax = 4;
- static const int kBucketsMax = kScoreMax * AUTH_EVENT_MAX + 1;
- DCHECK(handler->score() >= kScoreMin && handler->score() <= kScoreMax);
- int bucket = (handler->score() - kScoreMin) * AUTH_EVENT_MAX + auth_event;
- UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthCount", bucket, kBucketsMax);
+ static const int kEventBucketsEnd =
+ HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_EVENT_MAX;
+ int event_bucket = auth_scheme * AUTH_EVENT_MAX + auth_event;
+ DCHECK(event_bucket >= 0 && event_bucket < kEventBucketsEnd);
+ UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthCount", event_bucket,
+ kEventBucketsEnd);
+
+ // Record the target of the authentication.
+ //
+ // The results map to:
+ // Basic Proxy: 0
+ // Basic Secure Proxy: 1
+ // Basic Server: 2
+ // Basic Secure Server: 3
+ // Digest Proxy: 4
+ // Digest Secure Proxy: 5
+ // Digest Server: 6
+ // Digest Secure Server: 7
+ // NTLM Proxy: 8
+ // NTLM Secure Proxy: 9
+ // NTLM Server: 10
+ // NTLM Secure Server: 11
+ // Negotiate Proxy: 12
+ // Negotiate Secure Proxy: 13
+ // Negotiate Server: 14
+ // Negotiate Secure Server: 15
+ if (auth_event != AUTH_EVENT_START)
+ return;
+ static const int kTargetBucketsEnd =
+ HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_TARGET_MAX;
+ AuthTarget auth_target = DetermineAuthTarget(handler);
+ int target_bucket = auth_scheme * AUTH_TARGET_MAX + auth_target;
+ DCHECK(target_bucket >= 0 && target_bucket < kTargetBucketsEnd);
+ UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthTarget", target_bucket,
+ kTargetBucketsEnd);
}
} // namespace
@@ -334,6 +393,14 @@ void HttpAuthController::ResetAuth(const string16& username,
}
}
+bool HttpAuthController::HaveAuthHandler() const {
+ return handler_.get() != NULL;
+}
+
+bool HttpAuthController::HaveAuth() const {
+ return handler_.get() && !identity_.invalid;
+}
+
void HttpAuthController::InvalidateCurrentHandler() {
DCHECK(CalledOnValidThread());
diff --git a/net/http/http_auth_controller.h b/net/http/http_auth_controller.h
index bcda707..1d0a5cd 100644
--- a/net/http/http_auth_controller.h
+++ b/net/http/http_auth_controller.h
@@ -63,13 +63,9 @@ class HttpAuthController : public base::RefCounted<HttpAuthController>,
virtual void ResetAuth(const string16& username,
const string16& password);
- virtual bool HaveAuthHandler() const {
- return handler_.get() != NULL;
- }
+ virtual bool HaveAuthHandler() const;
- virtual bool HaveAuth() const {
- return handler_.get() && !identity_.invalid;
- }
+ virtual bool HaveAuth() const;
virtual scoped_refptr<AuthChallengeInfo> auth_info();
diff --git a/net/http/http_auth_gssapi_posix.cc b/net/http/http_auth_gssapi_posix.cc
index bd2734f..c492b1b 100644
--- a/net/http/http_auth_gssapi_posix.cc
+++ b/net/http/http_auth_gssapi_posix.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
+#include "base/thread_restrictions.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
@@ -446,6 +447,10 @@ base::NativeLibrary GSSAPISharedLibrary::LoadSharedLibrary() {
for (size_t i = 0; i < num_lib_names; ++i) {
const char* library_name = library_names[i];
FilePath file_path(library_name);
+
+ // TODO(asanka): Move library loading to a separate thread.
+ // http://crbug.com/66702
+ base::ThreadRestrictions::ScopedAllowIO allow_io_temporarily;
base::NativeLibrary lib = base::LoadNativeLibrary(file_path);
if (lib) {
// Only return this library if we can bind the functions we need.
diff --git a/net/http/http_auth_handler.cc b/net/http/http_auth_handler.cc
index d6e6a62..5c86d69 100644
--- a/net/http/http_auth_handler.cc
+++ b/net/http/http_auth_handler.cc
@@ -13,7 +13,8 @@
namespace net {
HttpAuthHandler::HttpAuthHandler()
- : score_(-1),
+ : auth_scheme_(AUTH_SCHEME_MAX),
+ score_(-1),
target_(HttpAuth::AUTH_NONE),
properties_(-1),
original_callback_(NULL),
@@ -50,6 +51,7 @@ bool HttpAuthHandler::InitFromChallenge(
DCHECK(!ok || !scheme().empty());
DCHECK(!ok || score_ != -1);
DCHECK(!ok || properties_ != -1);
+ DCHECK(!ok || auth_scheme_ != AUTH_SCHEME_MAX);
if (ok)
histogram_ = base::Histogram::FactoryTimeGet(
@@ -99,6 +101,14 @@ int HttpAuthHandler::GenerateAuthToken(const string16* username,
return rv;
}
+bool HttpAuthHandler::NeedsIdentity() {
+ return true;
+}
+
+bool HttpAuthHandler::AllowsDefaultCredentials() {
+ return false;
+}
+
void HttpAuthHandler::OnGenerateAuthTokenComplete(int rv) {
CompletionCallback* callback = original_callback_;
FinishGenerateAuthToken();
diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h
index 908b065..b48d4c2 100644
--- a/net/http/http_auth_handler.h
+++ b/net/http/http_auth_handler.h
@@ -27,6 +27,14 @@ struct HttpRequestInfo;
// HttpAuthHandler objects are typically created by an HttpAuthHandlerFactory.
class HttpAuthHandler {
public:
+ enum AuthScheme {
+ AUTH_SCHEME_BASIC = 0,
+ AUTH_SCHEME_DIGEST,
+ AUTH_SCHEME_NTLM,
+ AUTH_SCHEME_NEGOTIATE,
+ AUTH_SCHEME_MAX,
+ };
+
HttpAuthHandler();
virtual ~HttpAuthHandler();
@@ -80,6 +88,11 @@ class HttpAuthHandler {
CompletionCallback* callback,
std::string* auth_token);
+ // The authentication scheme as an enumerated value.
+ AuthScheme auth_scheme() const {
+ return auth_scheme_;
+ }
+
// Lowercase name of the auth scheme
const std::string& scheme() const {
return scheme_;
@@ -105,6 +118,13 @@ class HttpAuthHandler {
return target_;
}
+ // Returns the proxy or server which issued the authentication challenge
+ // that this HttpAuthHandler is handling. The URL includes scheme, host, and
+ // port, but does not include path.
+ const GURL& origin() const {
+ return origin_;
+ }
+
// Returns true if the authentication scheme does not send the username and
// password in the clear.
bool encrypts_identity() const {
@@ -123,14 +143,14 @@ class HttpAuthHandler {
// requires an identity.
// TODO(wtc): Find a better way to handle a multi-round challenge-response
// sequence used by a connection-based authentication scheme.
- virtual bool NeedsIdentity() { return true; }
+ virtual bool NeedsIdentity();
// Returns whether the default credentials may be used for the |origin| passed
// into |InitFromChallenge|. If true, the user does not need to be prompted
// for username and password to establish credentials.
// NOTE: SSO is a potential security risk.
// TODO(cbentzel): Add a pointer to Firefox documentation about risk.
- virtual bool AllowsDefaultCredentials() { return false; }
+ virtual bool AllowsDefaultCredentials();
protected:
enum Property {
@@ -155,6 +175,9 @@ class HttpAuthHandler {
CompletionCallback* callback,
std::string* auth_token) = 0;
+ // The auth-scheme as an enumerated value.
+ AuthScheme auth_scheme_;
+
// The lowercase auth-scheme {"basic", "digest", "ntlm", "negotiate"}
std::string scheme_;
diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc
index 35b088f..8ee775d 100644
--- a/net/http/http_auth_handler_basic.cc
+++ b/net/http/http_auth_handler_basic.cc
@@ -23,6 +23,7 @@ namespace net {
// We allow it to be compatibility with certain embedded webservers that don't
// include a realm (see http://crbug.com/20984.)
bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) {
+ auth_scheme_ = AUTH_SCHEME_BASIC;
scheme_ = "basic";
score_ = 1;
properties_ = 0;
diff --git a/net/http/http_auth_handler_basic.h b/net/http/http_auth_handler_basic.h
index a9031bb..a48c5d8 100644
--- a/net/http/http_auth_handler_basic.h
+++ b/net/http/http_auth_handler_basic.h
@@ -31,7 +31,7 @@ class HttpAuthHandlerBasic : public HttpAuthHandler {
scoped_ptr<HttpAuthHandler>* handler);
};
- HttpAuth::AuthorizationResult HandleAnotherChallenge(
+ virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
HttpAuth::ChallengeTokenizer* challenge);
protected:
diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc
index 517558f..2b103f4 100644
--- a/net/http/http_auth_handler_digest.cc
+++ b/net/http/http_auth_handler_digest.cc
@@ -266,6 +266,7 @@ HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
// webserver was not sending the realm with a BASIC challenge).
bool HttpAuthHandlerDigest::ParseChallenge(
HttpAuth::ChallengeTokenizer* challenge) {
+ auth_scheme_ = AUTH_SCHEME_DIGEST;
scheme_ = "digest";
score_ = 2;
properties_ = ENCRYPTS_IDENTITY;
diff --git a/net/http/http_auth_handler_digest.h b/net/http/http_auth_handler_digest.h
index 25cf16a..c319f5d 100644
--- a/net/http/http_auth_handler_digest.h
+++ b/net/http/http_auth_handler_digest.h
@@ -77,7 +77,7 @@ class HttpAuthHandlerDigest : public HttpAuthHandler {
scoped_ptr<const NonceGenerator> nonce_generator_;
};
- HttpAuth::AuthorizationResult HandleAnotherChallenge(
+ virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
HttpAuth::ChallengeTokenizer* challenge);
protected:
diff --git a/net/http/http_auth_handler_digest_unittest.cc b/net/http/http_auth_handler_digest_unittest.cc
index 9338bca..9b57c16 100644
--- a/net/http/http_auth_handler_digest_unittest.cc
+++ b/net/http/http_auth_handler_digest_unittest.cc
@@ -15,6 +15,73 @@
namespace net {
+namespace {
+
+const char* const kSimpleChallenge =
+ "Digest realm=\"Oblivion\", nonce=\"nonce-value\"";
+
+// RespondToChallenge creates an HttpAuthHandlerDigest for the specified
+// |challenge|, and generates a response to the challenge which is returned in
+// |token|.
+//
+// The return value indicates whether the |token| was successfully created.
+//
+// If |target| is HttpAuth::AUTH_PROXY, then |proxy_name| specifies the source
+// of the |challenge|. Otherwise, the scheme and host and port of |request_url|
+// indicates the origin of the challenge.
+bool RespondToChallenge(HttpAuth::Target target,
+ const std::string& proxy_name,
+ const std::string& request_url,
+ const std::string& challenge,
+ std::string* token) {
+ // Input validation.
+ if (token == NULL) {
+ ADD_FAILURE() << "|token| must be non-NULL";
+ return false;
+ }
+ EXPECT_TRUE(target != HttpAuth::AUTH_PROXY || !proxy_name.empty());
+ EXPECT_FALSE(request_url.empty());
+ EXPECT_FALSE(challenge.empty());
+
+ token->clear();
+ scoped_ptr<HttpAuthHandlerDigest::Factory> factory(
+ new HttpAuthHandlerDigest::Factory());
+ HttpAuthHandlerDigest::NonceGenerator* nonce_generator =
+ new HttpAuthHandlerDigest::FixedNonceGenerator("client_nonce");
+ factory->set_nonce_generator(nonce_generator);
+ scoped_ptr<HttpAuthHandler> handler;
+
+ // Create a handler for a particular challenge.
+ GURL url_origin(target == HttpAuth::AUTH_SERVER ? request_url : proxy_name);
+ int rv_create = factory->CreateAuthHandlerFromString(
+ challenge, target, url_origin.GetOrigin(), BoundNetLog(), &handler);
+ if (rv_create != OK || handler.get() == NULL) {
+ ADD_FAILURE() << "Unable to create auth handler.";
+ return false;
+ }
+
+ // Create a token in response to the challenge.
+ // NOTE: HttpAuthHandlerDigest's implementation of GenerateAuthToken always
+ // completes synchronously. That's why this test can get away with a
+ // TestCompletionCallback without an IO thread.
+ TestCompletionCallback callback;
+ scoped_ptr<HttpRequestInfo> request(new HttpRequestInfo());
+ request->url = GURL(request_url);
+ const string16 kFoo = ASCIIToUTF16("foo");
+ const string16 kBar = ASCIIToUTF16("bar");
+ int rv_generate = handler->GenerateAuthToken(
+ &kFoo, &kBar, request.get(), &callback, token);
+ if (rv_generate != OK) {
+ ADD_FAILURE() << "Problems generating auth token";
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+
TEST(HttpAuthHandlerDigestTest, ParseChallenge) {
static const struct {
// The challenge string.
@@ -488,75 +555,14 @@ TEST(HttpAuthHandlerDigest, HandleAnotherChallenge) {
handler->HandleAnotherChallenge(&tok_stale_false));
}
-namespace {
-
-const char* const kSimpleChallenge =
- "Digest realm=\"Oblivion\", nonce=\"nonce-value\"";
-
-// RespondToChallenge creates an HttpAuthHandlerDigest for the specified
-// |challenge|, and generates a response to the challenge which is returned in
-// |token|.
-//
-// The return value is an error string - an empty string indicates no errors.
-//
-// If |target| is HttpAuth::AUTH_PROXY, then |proxy_name| specifies the source
-// of the |challenge|. Otherwise, the scheme and host and port of |request_url|
-// indicates the origin of the challenge.
-std::string RespondToChallenge(HttpAuth::Target target,
- const std::string& proxy_name,
- const std::string& request_url,
- const std::string& challenge,
- std::string* token) {
- // Input validation.
- DCHECK(token);
- DCHECK(target != HttpAuth::AUTH_PROXY || !proxy_name.empty());
- DCHECK(!request_url.empty());
- DCHECK(!challenge.empty());
-
- token->clear();
- scoped_ptr<HttpAuthHandlerDigest::Factory> factory(
- new HttpAuthHandlerDigest::Factory());
- HttpAuthHandlerDigest::NonceGenerator* nonce_generator =
- new HttpAuthHandlerDigest::FixedNonceGenerator("client_nonce");
- factory->set_nonce_generator(nonce_generator);
- scoped_ptr<HttpAuthHandler> handler;
-
- // Create a handler for a particular challenge.
- GURL url_origin(target == HttpAuth::AUTH_SERVER ? request_url : proxy_name);
- int rv_create = factory->CreateAuthHandlerFromString(
- challenge, target, url_origin.GetOrigin(), BoundNetLog(), &handler);
- if (rv_create != OK || handler.get() == NULL)
- return "Unable to create auth handler.";
-
- // Create a token in response to the challenge.
- // NOTE: HttpAuthHandlerDigest's implementation of GenerateAuthToken always
- // completes synchronously. That's why this test can get away with a
- // TestCompletionCallback without an IO thread.
- TestCompletionCallback callback;
- scoped_ptr<HttpRequestInfo> request(new HttpRequestInfo());
- request->url = GURL(request_url);
- const string16 kFoo = ASCIIToUTF16("foo");
- const string16 kBar = ASCIIToUTF16("bar");
- int rv_generate = handler->GenerateAuthToken(
- &kFoo, &kBar, request.get(), &callback, token);
- if (rv_generate != OK)
- return "Problems generating auth token";
-
- // The token was correctly generated and is returned in |token|.
- return std::string();
-}
-
-} // namespace
-
TEST(HttpAuthHandlerDigest, RespondToServerChallenge) {
std::string auth_token;
- std::string error_text = RespondToChallenge(
+ EXPECT_TRUE(RespondToChallenge(
HttpAuth::AUTH_SERVER,
std::string(),
"http://www.example.com/path/to/resource",
kSimpleChallenge,
- &auth_token);
- EXPECT_EQ("", error_text);
+ &auth_token));
EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", "
"nonce=\"nonce-value\", uri=\"/path/to/resource\", "
"response=\"6779f90bd0d658f937c1af967614fe84\"",
@@ -565,13 +571,12 @@ TEST(HttpAuthHandlerDigest, RespondToServerChallenge) {
TEST(HttpAuthHandlerDigest, RespondToHttpsServerChallenge) {
std::string auth_token;
- std::string error_text = RespondToChallenge(
+ EXPECT_TRUE(RespondToChallenge(
HttpAuth::AUTH_SERVER,
std::string(),
"https://www.example.com/path/to/resource",
kSimpleChallenge,
- &auth_token);
- EXPECT_EQ("", error_text);
+ &auth_token));
EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", "
"nonce=\"nonce-value\", uri=\"/path/to/resource\", "
"response=\"6779f90bd0d658f937c1af967614fe84\"",
@@ -580,13 +585,12 @@ TEST(HttpAuthHandlerDigest, RespondToHttpsServerChallenge) {
TEST(HttpAuthHandlerDigest, RespondToProxyChallenge) {
std::string auth_token;
- std::string error_text = RespondToChallenge(
+ EXPECT_TRUE(RespondToChallenge(
HttpAuth::AUTH_PROXY,
"http://proxy.intranet.corp.com:3128",
"http://www.example.com/path/to/resource",
kSimpleChallenge,
- &auth_token);
- EXPECT_EQ("", error_text);
+ &auth_token));
EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", "
"nonce=\"nonce-value\", uri=\"/path/to/resource\", "
"response=\"6779f90bd0d658f937c1af967614fe84\"",
@@ -595,13 +599,12 @@ TEST(HttpAuthHandlerDigest, RespondToProxyChallenge) {
TEST(HttpAuthHandlerDigest, RespondToProxyChallengeHttps) {
std::string auth_token;
- std::string error_text = RespondToChallenge(
+ EXPECT_TRUE(RespondToChallenge(
HttpAuth::AUTH_PROXY,
"http://proxy.intranet.corp.com:3128",
"https://www.example.com/path/to/resource",
kSimpleChallenge,
- &auth_token);
- EXPECT_EQ("", error_text);
+ &auth_token));
EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", "
"nonce=\"nonce-value\", uri=\"www.example.com:443\", "
"response=\"3270da8467afbe9ddf2334a48d46e9b9\"",
@@ -610,13 +613,12 @@ TEST(HttpAuthHandlerDigest, RespondToProxyChallengeHttps) {
TEST(HttpAuthHandlerDigest, RespondToChallengeAuthQop) {
std::string auth_token;
- std::string error_text = RespondToChallenge(
+ EXPECT_TRUE(RespondToChallenge(
HttpAuth::AUTH_SERVER,
std::string(),
"http://www.example.com/path/to/resource",
"Digest realm=\"Oblivion\", nonce=\"nonce-value\", qop=\"auth\"",
- &auth_token);
- EXPECT_EQ("", error_text);
+ &auth_token));
EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", "
"nonce=\"nonce-value\", uri=\"/path/to/resource\", "
"response=\"5b1459beda5cee30d6ff9e970a69c0ea\", "
@@ -626,14 +628,13 @@ TEST(HttpAuthHandlerDigest, RespondToChallengeAuthQop) {
TEST(HttpAuthHandlerDigest, RespondToChallengeOpaque) {
std::string auth_token;
- std::string error_text = RespondToChallenge(
+ EXPECT_TRUE(RespondToChallenge(
HttpAuth::AUTH_SERVER,
std::string(),
"http://www.example.com/path/to/resource",
"Digest realm=\"Oblivion\", nonce=\"nonce-value\", "
"qop=\"auth\", opaque=\"opaque text\"",
- &auth_token);
- EXPECT_EQ("", error_text);
+ &auth_token));
EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", "
"nonce=\"nonce-value\", uri=\"/path/to/resource\", "
"response=\"5b1459beda5cee30d6ff9e970a69c0ea\", "
diff --git a/net/http/http_auth_handler_mock.cc b/net/http/http_auth_handler_mock.cc
index d1e8bb2..0a49169 100644
--- a/net/http/http_auth_handler_mock.cc
+++ b/net/http/http_auth_handler_mock.cc
@@ -72,6 +72,7 @@ void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) {
}
bool HttpAuthHandlerMock::Init(HttpAuth::ChallengeTokenizer* challenge) {
+ auth_scheme_ = AUTH_SCHEME_BASIC;
scheme_ = "mock";
score_ = 1;
properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc
index 0fce354..2544728 100644
--- a/net/http/http_auth_handler_negotiate.cc
+++ b/net/http/http_auth_handler_negotiate.cc
@@ -93,6 +93,7 @@ bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* challenge) {
#endif
if (CanDelegate())
auth_system_.Delegate();
+ auth_scheme_ = AUTH_SCHEME_NEGOTIATE;
scheme_ = "negotiate";
score_ = 4;
properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
diff --git a/net/http/http_auth_handler_ntlm.cc b/net/http/http_auth_handler_ntlm.cc
index 352b2ed..f987e48 100644
--- a/net/http/http_auth_handler_ntlm.cc
+++ b/net/http/http_auth_handler_ntlm.cc
@@ -93,6 +93,7 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
}
bool HttpAuthHandlerNTLM::Init(HttpAuth::ChallengeTokenizer* tok) {
+ auth_scheme_ = AUTH_SCHEME_NTLM;
scheme_ = "ntlm";
score_ = 3;
properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
diff --git a/net/http/http_auth_handler_unittest.cc b/net/http/http_auth_handler_unittest.cc
index d63b9fb..c3d0114 100644
--- a/net/http/http_auth_handler_unittest.cc
+++ b/net/http/http_auth_handler_unittest.cc
@@ -49,11 +49,12 @@ TEST(HttpAuthHandlerTest, NetLog) {
if (async)
test_callback.WaitForResult();
- EXPECT_EQ(2u, capturing_net_log.entries().size());
- EXPECT_TRUE(LogContainsBeginEvent(capturing_net_log.entries(),
- 0, event_type));
- EXPECT_TRUE(LogContainsEndEvent(capturing_net_log.entries(),
- 1, event_type));
+ net::CapturingNetLog::EntryList entries;
+ capturing_net_log.GetEntries(&entries);
+
+ EXPECT_EQ(2u, entries.size());
+ EXPECT_TRUE(LogContainsBeginEvent(entries, 0, event_type));
+ EXPECT_TRUE(LogContainsEndEvent(entries, 1, event_type));
}
}
}
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index 64352c4..061bb30 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -16,8 +16,10 @@
namespace net {
HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection,
+ HttpStreamParser* parser,
bool using_proxy)
: read_buf_(new GrowableIOBuffer()),
+ parser_(parser),
connection_(connection),
using_proxy_(using_proxy),
request_info_(NULL) {
@@ -26,6 +28,7 @@ HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection,
int HttpBasicStream::InitializeStream(const HttpRequestInfo* request_info,
const BoundNetLog& net_log,
CompletionCallback* callback) {
+ DCHECK(!parser_.get());
request_info_ = request_info;
parser_.reset(new HttpStreamParser(connection_.get(), request_info,
read_buf_, net_log));
@@ -38,6 +41,7 @@ int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
HttpResponseInfo* response,
CompletionCallback* callback) {
DCHECK(parser_.get());
+ DCHECK(request_info_);
const std::string path = using_proxy_ ?
HttpUtil::SpecForRequest(request_info_->url) :
HttpUtil::PathForRequest(request_info_->url);
@@ -75,7 +79,7 @@ HttpStream* HttpBasicStream::RenewStreamForAuth() {
DCHECK(IsResponseBodyComplete());
DCHECK(!IsMoreDataBuffered());
parser_.reset();
- return new HttpBasicStream(connection_.release(), using_proxy_);
+ return new HttpBasicStream(connection_.release(), NULL, using_proxy_);
}
bool HttpBasicStream::IsResponseBodyComplete() const {
diff --git a/net/http/http_basic_stream.h b/net/http/http_basic_stream.h
index 83136c0..918596a 100644
--- a/net/http/http_basic_stream.h
+++ b/net/http/http_basic_stream.h
@@ -30,7 +30,13 @@ class UploadDataStream;
class HttpBasicStream : public HttpStream {
public:
- HttpBasicStream(ClientSocketHandle* connection, bool using_proxy);
+ // Constructs a new HttpBasicStream. If |parser| is NULL, then
+ // InitializeStream should be called to initialize it correctly. If
+ // |parser| is non-null, then InitializeStream should not be called,
+ // as the stream is already initialized.
+ HttpBasicStream(ClientSocketHandle* connection,
+ HttpStreamParser* parser,
+ bool using_proxy);
virtual ~HttpBasicStream();
// HttpStream methods:
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 896a6ac..51cc55f 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -263,7 +263,7 @@ void HttpCache::MetadataWriter::OnIOComplete(int result) {
class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory {
public:
- SSLHostInfoFactoryAdaptor(HttpCache* http_cache)
+ explicit SSLHostInfoFactoryAdaptor(HttpCache* http_cache)
: http_cache_(http_cache) {
}
@@ -279,6 +279,7 @@ class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory {
//-----------------------------------------------------------------------------
HttpCache::HttpCache(HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker_,
ProxyService* proxy_service,
@@ -293,12 +294,11 @@ HttpCache::HttpCache(HostResolver* host_resolver,
ssl_host_info_factory_(new SSLHostInfoFactoryAdaptor(
ALLOW_THIS_IN_INITIALIZER_LIST(this))),
network_layer_(HttpNetworkLayer::CreateFactory(host_resolver,
- dnsrr_resolver, dns_cert_checker_,
+ cert_verifier, dnsrr_resolver, dns_cert_checker_,
ssl_host_info_factory_.get(),
proxy_service, ssl_config_service,
http_auth_handler_factory, network_delegate, net_log)),
- ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
- enable_range_support_(true) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
}
HttpCache::HttpCache(HttpNetworkSession* session,
@@ -307,8 +307,7 @@ HttpCache::HttpCache(HttpNetworkSession* session,
building_backend_(false),
mode_(NORMAL),
network_layer_(HttpNetworkLayer::CreateFactory(session)),
- ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
- enable_range_support_(true) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
}
HttpCache::HttpCache(HttpTransactionFactory* network_layer,
@@ -317,8 +316,7 @@ HttpCache::HttpCache(HttpTransactionFactory* network_layer,
building_backend_(false),
mode_(NORMAL),
network_layer_(network_layer),
- ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
- enable_range_support_(true) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
}
HttpCache::~HttpCache() {
@@ -385,7 +383,7 @@ int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) {
if (!disk_cache_.get())
CreateBackend(NULL, NULL); // We don't care about the result.
- trans->reset(new HttpCache::Transaction(this, enable_range_support_));
+ trans->reset(new HttpCache::Transaction(this));
return OK;
}
@@ -421,8 +419,7 @@ void HttpCache::WriteMetadata(const GURL& url,
if (!disk_cache_.get())
CreateBackend(NULL, NULL); // We don't care about the result.
- HttpCache::Transaction* trans =
- new HttpCache::Transaction(this, enable_range_support_);
+ HttpCache::Transaction* trans = new HttpCache::Transaction(this);
MetadataWriter* writer = new MetadataWriter(trans);
// The writer will self destruct when done.
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 06c2ab9..5c812da 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -41,6 +41,7 @@ class Entry;
namespace net {
+class CertVerifier;
class DnsCertProvenanceChecker;
class DnsRRResolver;
class HostResolver;
@@ -117,6 +118,7 @@ class HttpCache : public HttpTransactionFactory,
// The disk cache is initialized lazily (by CreateTransaction) in this case.
// The HttpCache takes ownership of the |backend_factory|.
HttpCache(HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
ProxyService* proxy_service,
@@ -179,10 +181,6 @@ class HttpCache : public HttpTransactionFactory,
// immediately, but they will not be reusable. This is for debugging.
void CloseCurrentConnections();
- void set_enable_range_support(bool value) {
- enable_range_support_ = value;
- }
-
protected:
// Disk cache entry data indices.
enum {
@@ -368,8 +366,6 @@ class HttpCache : public HttpTransactionFactory,
ScopedRunnableMethodFactory<HttpCache> task_factory_;
- bool enable_range_support_;
-
typedef base::hash_map<std::string, int> PlaybackCacheMap;
scoped_ptr<PlaybackCacheMap> playback_cache_map_;
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 1720509..923ee25 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -97,7 +97,7 @@ static bool HeaderMatches(const HttpRequestHeaders& headers,
//-----------------------------------------------------------------------------
-HttpCache::Transaction::Transaction(HttpCache* cache, bool enable_range_support)
+HttpCache::Transaction::Transaction(HttpCache* cache)
: next_state_(STATE_NONE),
request_(NULL),
cache_(cache->AsWeakPtr()),
@@ -110,7 +110,6 @@ HttpCache::Transaction::Transaction(HttpCache* cache, bool enable_range_support)
target_state_(STATE_NONE),
reading_(false),
invalid_range_(false),
- enable_range_support_(enable_range_support),
truncated_(false),
is_sparse_(false),
server_responded_206_(false),
@@ -139,7 +138,7 @@ HttpCache::Transaction::~Transaction() {
if (cache_) {
if (entry_) {
- bool cancel_request = reading_ && enable_range_support_;
+ bool cancel_request = reading_;
if (cancel_request) {
if (partial_.get()) {
entry_->disk_entry->CancelSparseIO();
@@ -683,7 +682,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
DoneWritingToEntry(false);
}
- if (enable_range_support_ && new_response_->headers->response_code() == 416) {
+ if (new_response_->headers->response_code() == 416) {
DCHECK_EQ(NONE, mode_);
response_ = *new_response_;
return OK;
@@ -1284,13 +1283,8 @@ void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log,
bool range_found = false;
bool external_validation_error = false;
- if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange)) {
- if (enable_range_support_) {
- range_found = true;
- } else {
- effective_load_flags_ |= LOAD_DISABLE_CACHE;
- }
- }
+ if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange))
+ range_found = true;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSpecialHeaders); ++i) {
if (HeaderMatches(request_->extra_headers, kSpecialHeaders[i].search)) {
@@ -1429,9 +1423,6 @@ int HttpCache::Transaction::BeginPartialCacheValidation() {
!truncated_)
return BeginCacheValidation();
- if (!enable_range_support_)
- return BeginCacheValidation();
-
bool byte_range_requested = partial_.get() != NULL;
if (byte_range_requested) {
next_state_ = STATE_CACHE_QUERY_DATA;
@@ -1552,9 +1543,6 @@ bool HttpCache::Transaction::RequiresValidation() {
if (effective_load_flags_ & LOAD_VALIDATE_CACHE)
return true;
- if (response_.headers->response_code() == 206 && !enable_range_support_)
- return true;
-
if (response_.headers->RequiresValidation(
response_.request_time, response_.response_time, Time::Now()))
return true;
@@ -1570,11 +1558,6 @@ bool HttpCache::Transaction::RequiresValidation() {
bool HttpCache::Transaction::ConditionalizeRequest() {
DCHECK(response_.headers);
- if (!enable_range_support_ && response_.headers->response_code() != 200) {
- // This only makes sense for cached 200 responses.
- return false;
- }
-
// This only makes sense for cached 200 or 206 responses.
if (response_.headers->response_code() != 200 &&
response_.headers->response_code() != 206)
@@ -1653,7 +1636,7 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
bool HttpCache::Transaction::ValidatePartialResponse(bool* partial_content) {
const HttpResponseHeaders* headers = new_response_->headers;
int response_code = headers->response_code();
- bool partial_response = enable_range_support_ ? response_code == 206 : false;
+ bool partial_response = (response_code == 206);
*partial_content = false;
if (!entry_)
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index a842ade..bc0b211 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -28,7 +28,7 @@ struct HttpRequestInfo;
// factory.
class HttpCache::Transaction : public HttpTransaction {
public:
- Transaction(HttpCache* cache, bool enable_range_support);
+ Transaction(HttpCache* cache);
virtual ~Transaction();
// HttpTransaction methods:
@@ -339,7 +339,6 @@ class HttpCache::Transaction : public HttpTransaction {
State target_state_;
bool reading_; // We are already reading.
bool invalid_range_; // We may bypass the cache for this request.
- bool enable_range_support_;
bool truncated_; // We don't have all the response data.
bool is_sparse_; // The data is stored in sparse byte ranges.
bool server_responded_206_;
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index b4dde9b..a40a5b8 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -1044,19 +1044,22 @@ TEST(HttpCache, SimpleGETNoDiskCache) {
// Check that the NetLog was filled as expected.
// (We attempted to both Open and Create entries, but both failed).
- EXPECT_EQ(6u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(6u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
+ entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
+ entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
+ entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
+ entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
EXPECT_EQ(1, cache.network_layer()->transaction_count());
EXPECT_EQ(0, cache.disk_cache()->open_count());
@@ -1145,23 +1148,26 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
log.bound());
// Check that the NetLog was filled as expected.
- EXPECT_EQ(8u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(8u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
+ entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
+ entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
+ entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
+ entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 6, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 6, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 7, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 7, net::NetLog::TYPE_HTTP_CACHE_WAITING));
// force this transaction to read from the cache
MockTransaction transaction(kSimpleGET_Transaction);
@@ -1172,23 +1178,25 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
// Check that the NetLog was filled as expected.
- EXPECT_EQ(8u, log.entries().size());
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(8u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
+ entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
+ entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 4, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 4, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 5, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 5, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 6, net::NetLog::TYPE_HTTP_CACHE_READ_INFO));
+ entries, 6, net::NetLog::TYPE_HTTP_CACHE_READ_INFO));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 7, net::NetLog::TYPE_HTTP_CACHE_READ_INFO));
+ entries, 7, net::NetLog::TYPE_HTTP_CACHE_READ_INFO));
EXPECT_EQ(1, cache.network_layer()->transaction_count());
EXPECT_EQ(1, cache.disk_cache()->open_count());
@@ -1268,23 +1276,26 @@ TEST(HttpCache, SimpleGET_LoadBypassCache) {
RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
// Check that the NetLog was filled as expected.
- EXPECT_EQ(8u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(8u, entries.size());
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 0, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 1, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 2, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
+ entries, 2, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 3, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
+ entries, 3, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
+ entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
+ entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 6, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 6, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_TRUE(net::LogContainsEndEvent(
- log.entries(), 7, net::NetLog::TYPE_HTTP_CACHE_WAITING));
+ entries, 7, net::NetLog::TYPE_HTTP_CACHE_WAITING));
EXPECT_EQ(2, cache.network_layer()->transaction_count());
EXPECT_EQ(0, cache.disk_cache()->open_count());
@@ -2767,7 +2778,6 @@ TEST(HttpCache, RangeGET_SkipsCache) {
// header.
TEST(HttpCache, RangeGET_SkipsCache2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockTransaction transaction(kRangeGET_Transaction);
transaction.request_headers = "If-None-Match: foo\r\n"
@@ -2802,7 +2812,6 @@ TEST(HttpCache, RangeGET_SkipsCache2) {
// Tests that receiving 206 for a regular request is handled correctly.
TEST(HttpCache, GET_Crazy206) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
// Write to the cache.
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -2828,7 +2837,6 @@ TEST(HttpCache, GET_Crazy206) {
// cache and the network.
TEST(HttpCache, RangeGET_OK) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -2884,7 +2892,6 @@ TEST(HttpCache, RangeGET_OK) {
// cache and the network, with synchronous responses.
TEST(HttpCache, RangeGET_SyncOK) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockTransaction transaction(kRangeGET_TransactionOK);
transaction.test_mode = TEST_MODE_SYNC_ALL;
@@ -2939,7 +2946,6 @@ TEST(HttpCache, RangeGET_SyncOK) {
// Tests that we don't revalidate an entry unless we are required to do so.
TEST(HttpCache, RangeGET_Revalidate1) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
// Write to the cache (40-49).
@@ -2981,7 +2987,6 @@ TEST(HttpCache, RangeGET_Revalidate1) {
// Checks that we revalidate an entry when the headers say so.
TEST(HttpCache, RangeGET_Revalidate2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
// Write to the cache (40-49).
@@ -3014,7 +3019,6 @@ TEST(HttpCache, RangeGET_Revalidate2) {
// Tests that we deal with 304s for range requests.
TEST(HttpCache, RangeGET_304) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -3045,7 +3049,6 @@ TEST(HttpCache, RangeGET_304) {
// Tests that we deal with 206s when revalidating range requests.
TEST(HttpCache, RangeGET_ModifiedResult) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -3083,7 +3086,6 @@ TEST(HttpCache, RangeGET_ModifiedResult) {
// We start with one suffix request, followed by a request from a given point.
TEST(HttpCache, UnknownRangeGET_1) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -3119,7 +3121,6 @@ TEST(HttpCache, UnknownRangeGET_1) {
// We'll also verify that synchronous cache responses work as intended.
TEST(HttpCache, UnknownRangeGET_2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3158,7 +3159,6 @@ TEST(HttpCache, UnknownRangeGET_2) {
// up things.
TEST(HttpCache, UnknownRangeGET_304) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3187,7 +3187,6 @@ TEST(HttpCache, UnknownRangeGET_304) {
// Tests that we can handle non-range requests when we have cached a range.
TEST(HttpCache, GET_Previous206) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -3219,7 +3218,6 @@ TEST(HttpCache, GET_Previous206) {
// part of the object and the server replies with 304 (Not Modified).
TEST(HttpCache, GET_Previous206_NotModified) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockTransaction transaction(kRangeGET_TransactionOK);
AddMockTransaction(&transaction);
@@ -3260,7 +3258,6 @@ TEST(HttpCache, GET_Previous206_NotModified) {
// new content provided by the server (206).
TEST(HttpCache, GET_Previous206_NewContent) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -3302,7 +3299,6 @@ TEST(HttpCache, GET_Previous206_NewContent) {
// Tests that we can handle cached 206 responses that are not sparse.
TEST(HttpCache, GET_Previous206_NotSparse) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
// Create a disk cache entry that stores 206 headers while not being sparse.
disk_cache::Entry* entry;
@@ -3345,7 +3341,6 @@ TEST(HttpCache, GET_Previous206_NotSparse) {
// we issue a range request and expect to receive a range.
TEST(HttpCache, RangeGET_Previous206_NotSparse_2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
// Create a disk cache entry that stores 206 headers while not being sparse.
@@ -3387,7 +3382,6 @@ TEST(HttpCache, RangeGET_Previous206_NotSparse_2) {
// Tests that we can handle range requests with cached 200 responses.
TEST(HttpCache, RangeGET_Previous200) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
// Store the whole thing with status 200.
MockTransaction transaction(kTypicalGET_Transaction);
@@ -3458,7 +3452,6 @@ TEST(HttpCache, RangeGET_Previous200) {
// Tests that we can handle a 200 response when dealing with sparse entries.
TEST(HttpCache, RangeRequestResultsIn200) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -3499,7 +3492,6 @@ TEST(HttpCache, RangeRequestResultsIn200) {
// only deletes the entry if the resource has indeed changed.
TEST(HttpCache, RangeGET_MoreThanCurrentSize) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
std::string headers;
@@ -3533,7 +3525,6 @@ TEST(HttpCache, RangeGET_MoreThanCurrentSize) {
// Tests that we don't delete a sparse entry when we cancel a request.
TEST(HttpCache, RangeGET_Cancel) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
MockHttpRequest request(kRangeGET_TransactionOK);
@@ -3571,7 +3562,6 @@ TEST(HttpCache, RangeGET_Cancel) {
// cancelling the previous one.
TEST(HttpCache, RangeGET_Cancel2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
@@ -3617,7 +3607,6 @@ TEST(HttpCache, RangeGET_Cancel2) {
// a row, making sure that the second is waiting for the entry to be ready.
TEST(HttpCache, RangeGET_Cancel3) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
@@ -3677,7 +3666,6 @@ TEST(HttpCache, RangeGET_Cancel3) {
// Tests that an invalid range response results in no cached entry.
TEST(HttpCache, RangeGET_InvalidResponse1) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3706,7 +3694,6 @@ TEST(HttpCache, RangeGET_InvalidResponse1) {
// Tests that we reject a range that doesn't match the content-length.
TEST(HttpCache, RangeGET_InvalidResponse2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3736,7 +3723,6 @@ TEST(HttpCache, RangeGET_InvalidResponse2) {
// ignore the response.
TEST(HttpCache, RangeGET_InvalidResponse3) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3784,7 +3770,6 @@ TEST(HttpCache, RangeGET_InvalidResponse3) {
TEST(HttpCache, RangeGET_LargeValues) {
// We need a real sparse cache for this test.
MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024));
- cache.http_cache()->set_enable_range_support(true);
std::string headers;
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3820,7 +3805,6 @@ TEST(HttpCache, RangeGET_NoDiskCache) {
factory->FinishCreation(); // We'll complete synchronously.
MockHttpCache cache(factory);
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
@@ -3832,7 +3816,6 @@ TEST(HttpCache, RangeGET_NoDiskCache) {
// Tests that we handle byte range requests that skip the cache.
TEST(HttpCache, RangeHEAD) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3855,7 +3838,6 @@ TEST(HttpCache, RangeHEAD) {
// request for the next range and the server gives us a 200 synchronously.
TEST(HttpCache, RangeGET_FastFlakyServer) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockTransaction transaction(kRangeGET_TransactionOK);
transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER;
@@ -3882,7 +3864,6 @@ TEST(HttpCache, RangeGET_FastFlakyServer) {
// asking for more data.
TEST(HttpCache, RangeGET_FastFlakyServer2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
// First, check with an empty cache (WRITE mode).
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -3923,7 +3904,6 @@ TEST(HttpCache, RangeGET_FastFlakyServer2) {
// This test hits a NOTREACHED so it is a release mode only test.
TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
// Write to the cache (40-49).
@@ -3988,7 +3968,6 @@ TEST(HttpCache, WriteResponseInfo_Truncated) {
// to read from the network.
TEST(HttpCache, DoomOnDestruction) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockHttpRequest request(kSimpleGET_Transaction);
@@ -4019,7 +3998,6 @@ TEST(HttpCache, DoomOnDestruction) {
// does not have content-length and strong validators.
TEST(HttpCache, DoomOnDestruction2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockHttpRequest request(kSimpleGET_Transaction);
@@ -4056,7 +4034,6 @@ TEST(HttpCache, DoomOnDestruction2) {
// has an "Accept-Ranges: none" header.
TEST(HttpCache, DoomOnDestruction3) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockTransaction transaction(kSimpleGET_Transaction);
transaction.response_headers =
@@ -4101,7 +4078,6 @@ TEST(HttpCache, DoomOnDestruction3) {
// Tests that we mark an entry as incomplete when the request is cancelled.
TEST(HttpCache, Set_Truncated_Flag) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
MockTransaction transaction(kSimpleGET_Transaction);
transaction.response_headers =
@@ -4162,7 +4138,6 @@ TEST(HttpCache, Set_Truncated_Flag) {
// Tests that we can continue with a request that was interrupted.
TEST(HttpCache, GET_IncompleteResource) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
// Create a disk cache entry that stores an incomplete resource.
@@ -4223,7 +4198,6 @@ TEST(HttpCache, GET_IncompleteResource) {
// Tests that we delete truncated entries if the server changes its mind midway.
TEST(HttpCache, GET_IncompleteResource2) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
// Create a disk cache entry that stores an incomplete resource.
@@ -4283,7 +4257,6 @@ TEST(HttpCache, GET_IncompleteResource2) {
// as truncated.
TEST(HttpCache, GET_CancelIncompleteResource) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
// Create a disk cache entry that stores an incomplete resource.
@@ -4349,7 +4322,6 @@ TEST(HttpCache, GET_CancelIncompleteResource) {
// Tests that we can handle range requests when we have a truncated entry.
TEST(HttpCache, RangeGET_IncompleteResource) {
MockHttpCache cache;
- cache.http_cache()->set_enable_range_support(true);
AddMockTransaction(&kRangeGET_TransactionOK);
// Create a disk cache entry that stores an incomplete resource.
diff --git a/net/http/http_net_log_params.h b/net/http/http_net_log_params.h
index 6a0b47b..1631363 100644
--- a/net/http/http_net_log_params.h
+++ b/net/http/http_net_log_params.h
@@ -24,7 +24,7 @@ class NetLogHttpRequestParameter : public NetLog::EventParameters {
NetLogHttpRequestParameter(const std::string& line,
const HttpRequestHeaders& headers);
- Value* ToValue() const;
+ virtual Value* ToValue() const;
const HttpRequestHeaders& GetHeaders() const {
return headers_;
@@ -48,7 +48,7 @@ class NetLogHttpResponseParameter : public NetLog::EventParameters {
explicit NetLogHttpResponseParameter(
const scoped_refptr<HttpResponseHeaders>& headers);
- Value* ToValue() const;
+ virtual Value* ToValue() const;
const HttpResponseHeaders& GetHeaders() const {
return *headers_;
diff --git a/net/http/http_network_layer.cc b/net/http/http_network_layer.cc
index 3da23c2..3d3c5dd 100644
--- a/net/http/http_network_layer.cc
+++ b/net/http/http_network_layer.cc
@@ -21,6 +21,7 @@ namespace net {
// static
HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -32,7 +33,7 @@ HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
DCHECK(proxy_service);
return new HttpNetworkLayer(ClientSocketFactory::GetDefaultFactory(),
- host_resolver, dnsrr_resolver,
+ host_resolver, cert_verifier, dnsrr_resolver,
dns_cert_checker,
ssl_host_info_factory, proxy_service,
ssl_config_service, http_auth_handler_factory,
@@ -52,6 +53,7 @@ HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
HttpNetworkLayer::HttpNetworkLayer(
ClientSocketFactory* socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -62,6 +64,7 @@ HttpNetworkLayer::HttpNetworkLayer(
NetLog* net_log)
: socket_factory_(socket_factory),
host_resolver_(host_resolver),
+ cert_verifier_(cert_verifier),
dnsrr_resolver_(dnsrr_resolver),
dns_cert_checker_(dns_cert_checker),
ssl_host_info_factory_(ssl_host_info_factory),
@@ -80,6 +83,7 @@ HttpNetworkLayer::HttpNetworkLayer(
HttpNetworkLayer::HttpNetworkLayer(
ClientSocketFactory* socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -91,6 +95,7 @@ HttpNetworkLayer::HttpNetworkLayer(
NetLog* net_log)
: socket_factory_(socket_factory),
host_resolver_(host_resolver),
+ cert_verifier_(cert_verifier),
dnsrr_resolver_(dnsrr_resolver),
dns_cert_checker_(dns_cert_checker),
ssl_host_info_factory_(ssl_host_info_factory),
@@ -108,6 +113,8 @@ HttpNetworkLayer::HttpNetworkLayer(
HttpNetworkLayer::HttpNetworkLayer(HttpNetworkSession* session)
: socket_factory_(ClientSocketFactory::GetDefaultFactory()),
+ host_resolver_(NULL),
+ cert_verifier_(NULL),
dnsrr_resolver_(NULL),
dns_cert_checker_(NULL),
ssl_host_info_factory_(NULL),
@@ -150,6 +157,7 @@ HttpNetworkSession* HttpNetworkLayer::GetSession() {
spdy_session_pool_.reset(new SpdySessionPool(ssl_config_service_));
session_ = new HttpNetworkSession(
host_resolver_,
+ cert_verifier_,
dnsrr_resolver_,
dns_cert_checker_,
ssl_host_info_factory_,
@@ -162,6 +170,7 @@ HttpNetworkSession* HttpNetworkLayer::GetSession() {
net_log_);
// These were just temps for lazy-initializing HttpNetworkSession.
host_resolver_ = NULL;
+ cert_verifier_ = NULL;
dnsrr_resolver_ = NULL;
dns_cert_checker_ = NULL;
ssl_host_info_factory_ = NULL;
diff --git a/net/http/http_network_layer.h b/net/http/http_network_layer.h
index 7781efb..91e1a86 100644
--- a/net/http/http_network_layer.h
+++ b/net/http/http_network_layer.h
@@ -15,6 +15,7 @@
namespace net {
+class CertVerifier;
class ClientSocketFactory;
class DnsCertProvenanceChecker;
class DnsRRResolver;
@@ -30,10 +31,12 @@ class SSLHostInfoFactory;
class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe {
public:
- // |socket_factory|, |proxy_service| and |host_resolver| must remain valid for
- // the lifetime of HttpNetworkLayer.
+ // |socket_factory|, |proxy_service|, |host_resolver|, etc. must remain
+ // valid for the lifetime of HttpNetworkLayer.
+ // TODO(wtc): we only need the next constructor.
HttpNetworkLayer(ClientSocketFactory* socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -42,11 +45,10 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe {
HttpAuthHandlerFactory* http_auth_handler_factory,
HttpNetworkDelegate* network_delegate,
NetLog* net_log);
- // Construct a HttpNetworkLayer with an existing HttpNetworkSession which
- // contains a valid ProxyService.
HttpNetworkLayer(
ClientSocketFactory* socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -57,6 +59,8 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe {
HttpNetworkDelegate* network_delegate,
NetLog* net_log);
+ // Construct a HttpNetworkLayer with an existing HttpNetworkSession which
+ // contains a valid ProxyService.
explicit HttpNetworkLayer(HttpNetworkSession* session);
~HttpNetworkLayer();
@@ -64,6 +68,7 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe {
// and allows other implementations to be substituted.
static HttpTransactionFactory* CreateFactory(
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -100,9 +105,10 @@ class HttpNetworkLayer : public HttpTransactionFactory, public NonThreadSafe {
// The factory we will use to create network sockets.
ClientSocketFactory* socket_factory_;
- // The host resolver and proxy service that will be used when lazily
+ // The host resolver, proxy service, etc. that will be used when lazily
// creating |session_|.
HostResolver* host_resolver_;
+ CertVerifier* cert_verifier_;
DnsRRResolver* dnsrr_resolver_;
DnsCertProvenanceChecker* dns_cert_checker_;
SSLHostInfoFactory* ssl_host_info_factory_;
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index 3ed54bf..2720c10 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/base/cert_verifier.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_log.h"
#include "net/base/ssl_config_service_defaults.h"
@@ -21,9 +22,11 @@ class HttpNetworkLayerTest : public PlatformTest {
TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
MockHostResolver host_resolver;
+ net::CertVerifier cert_verifier;
net::HttpNetworkLayer factory(
NULL,
&host_resolver,
+ &cert_verifier,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -41,9 +44,11 @@ TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
TEST_F(HttpNetworkLayerTest, Suspend) {
MockHostResolver host_resolver;
+ net::CertVerifier cert_verifier;
net::HttpNetworkLayer factory(
NULL,
&host_resolver,
+ &cert_verifier,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -90,9 +95,11 @@ TEST_F(HttpNetworkLayerTest, GET) {
mock_socket_factory.AddSocketDataProvider(&data);
MockHostResolver host_resolver;
+ net::CertVerifier cert_verifier;
net::HttpNetworkLayer factory(
&mock_socket_factory,
&host_resolver,
+ &cert_verifier,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 1e77b49..e3de475 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -20,6 +20,7 @@ namespace net {
// TODO(mbelshe): Move the socket factories into HttpStreamFactory.
HttpNetworkSession::HttpNetworkSession(
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -32,6 +33,7 @@ HttpNetworkSession::HttpNetworkSession(
NetLog* net_log)
: socket_factory_(client_socket_factory),
host_resolver_(host_resolver),
+ cert_verifier_(cert_verifier),
dnsrr_resolver_(dnsrr_resolver),
dns_cert_checker_(dns_cert_checker),
proxy_service_(proxy_service),
@@ -39,6 +41,7 @@ HttpNetworkSession::HttpNetworkSession(
socket_pool_manager_(net_log,
client_socket_factory,
host_resolver,
+ cert_verifier,
dnsrr_resolver,
dns_cert_checker,
ssl_host_info_factory,
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 43424d2..2c923b6 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -28,6 +28,7 @@ class Value;
namespace net {
+class CertVerifier;
class ClientSocketFactory;
class DnsCertProvenanceChecker;
class DnsRRResolver;
@@ -48,6 +49,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
public:
HttpNetworkSession(
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -109,6 +111,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
// SSL sockets come from the socket_factory().
ClientSocketFactory* socket_factory() { return socket_factory_; }
HostResolver* host_resolver() { return host_resolver_; }
+ CertVerifier* cert_verifier() { return cert_verifier_; }
DnsRRResolver* dnsrr_resolver() { return dnsrr_resolver_; }
DnsCertProvenanceChecker* dns_cert_checker() {
return dns_cert_checker_;
@@ -152,6 +155,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>,
SSLClientAuthCache ssl_client_auth_cache_;
HttpAlternateProtocols alternate_protocols_;
HostResolver* const host_resolver_;
+ CertVerifier* cert_verifier_;
DnsRRResolver* dnsrr_resolver_;
DnsCertProvenanceChecker* dns_cert_checker_;
scoped_refptr<ProxyService> proxy_service_;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 7621e5a..64a4fa7 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -285,11 +285,13 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
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
+ // to establish an SSL tunnel through an HTTP proxy. We can't read these
// bytes when establishing a tunnel because they might be controlled by
// an active network attacker. We don't worry about this for HTTP
// because an active network attacker can already control HTTP sessions.
- // We reach this case when the user cancels a 407 proxy auth prompt.
+ // We reach this case when the user cancels a 407 proxy auth prompt. We
+ // also don't worry about this for an HTTPS Proxy, because the
+ // communication with the proxy is secure.
// See http://crbug.com/8473.
DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
DCHECK_EQ(headers->response_code(), 407);
@@ -301,7 +303,6 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
// Are we using SPDY or HTTP?
next_state = STATE_READ_BODY;
- DCHECK(stream_->GetResponseInfo()->headers);
read_buf_ = buf;
read_buf_len_ = buf_len;
@@ -410,6 +411,18 @@ void HttpNetworkTransaction::OnNeedsClientAuth(
OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
}
+void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
+ const HttpResponseInfo& response_info,
+ HttpStream* stream) {
+ DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
+
+ headers_valid_ = true;
+ response_ = response_info;
+ stream_.reset(stream);
+ stream_request_.reset(); // we're done with the stream request
+ OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
+}
+
bool HttpNetworkTransaction::is_https_request() const {
return request_->url.SchemeIs("https");
}
@@ -535,12 +548,12 @@ int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
DCHECK(stream_.get());
} else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
result = HandleCertificateRequest(result);
+ } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
+ // Return OK and let the caller read the proxy's error page
+ next_state_ = STATE_NONE;
+ return OK;
}
- // Handle possible handshake errors that may have occurred if the stream
- // used SSL for one or more of the layers.
- result = HandleSSLHandshakeError(result);
-
// At this point we are done with the stream_request_.
stream_request_.reset();
return result;
@@ -683,6 +696,23 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
result = HandleCertificateRequest(result);
if (result == OK)
return result;
+ } else if ((result == ERR_SSL_DECOMPRESSION_FAILURE_ALERT ||
+ result == ERR_SSL_BAD_RECORD_MAC_ALERT) &&
+ ssl_config_.tls1_enabled &&
+ !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
+ // Some buggy servers select DEFLATE compression when offered and then
+ // fail to ever decompress anything. They will send a fatal alert telling
+ // us this. Normally we would pick this up during the handshake because
+ // our Finished message is compressed and we'll never get the server's
+ // Finished if it fails to process ours.
+ //
+ // However, with False Start, we'll believe that the handshake is
+ // complete as soon as we've /sent/ our Finished message. In this case,
+ // we only find out that the server is buggy here, when we try to read
+ // the initial reply.
+ session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
+ ResetConnectionAndRequestForResend();
+ return OK;
}
if (result < 0 && result != ERR_CONNECTION_CLOSED)
@@ -994,61 +1024,11 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) {
return OK;
}
-// TODO(rch): This does not correctly handle errors when an SSL proxy is
-// being used, as all of the errors are handled as if they were generated
-// by the endpoint host, request_->url, rather than considering if they were
-// generated by the SSL proxy. http://crbug.com/66424
-int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
- DCHECK(request_);
- if (ssl_config_.send_client_cert &&
- (error == ERR_SSL_PROTOCOL_ERROR ||
- error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
- session_->ssl_client_auth_cache()->Remove(
- GetHostAndPort(request_->url));
- }
-
- switch (error) {
- case ERR_SSL_PROTOCOL_ERROR:
- case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
- case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
- case ERR_SSL_BAD_RECORD_MAC_ALERT:
- if (ssl_config_.tls1_enabled &&
- !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
- // This could be a TLS-intolerant server, an SSL 3.0 server that
- // chose a TLS-only cipher suite or a server with buggy DEFLATE
- // support. Turn off TLS 1.0, DEFLATE support and retry.
- session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
- ResetConnectionAndRequestForResend();
- error = OK;
- }
- break;
- case ERR_SSL_SNAP_START_NPN_MISPREDICTION:
- // This means that we tried to Snap Start a connection, but we
- // mispredicted the NPN result. This isn't a problem from the point of
- // view of the SSL layer because the server will ignore the application
- // data in the Snap Start extension. However, at the HTTP layer, we have
- // already decided that it's a HTTP or SPDY connection and it's easier to
- // abort and start again.
- ResetConnectionAndRequestForResend();
- error = OK;
- break;
- }
- return error;
-}
-
// This method determines whether it is safe to resend the request after an
// IO error. It can only be called in response to request header or body
// write errors or response header read errors. It should not be used in
// other cases, such as a Connect error.
int HttpNetworkTransaction::HandleIOError(int error) {
- // SSL errors may happen at any time during the stream and indicate issues
- // with the underlying connection. Because the peer may request
- // renegotiation at any time, check and handle any possible SSL handshake
- // related errors. In addition to renegotiation, TLS False/Snap Start may
- // cause SSL handshake errors to be delayed until the first Read on the
- // underlying connection.
- error = HandleSSLHandshakeError(error);
-
switch (error) {
// If we try to reuse a connection that the server is in the process of
// closing, we may end up successfully writing out our request (or a
@@ -1062,6 +1042,16 @@ int HttpNetworkTransaction::HandleIOError(int error) {
error = OK;
}
break;
+ case ERR_SSL_SNAP_START_NPN_MISPREDICTION:
+ // This means that we tried to Snap Start a connection, but we
+ // mispredicted the NPN result. This isn't a problem from the point of
+ // view of the SSL layer because the server will ignore the application
+ // data in the Snap Start extension. However, at the HTTP layer, we have
+ // already decided that it's a HTTP or SPDY connection and it's easier to
+ // abort and start again.
+ ResetConnectionAndRequestForResend();
+ error = OK;
+ break;
}
return error;
}
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index 0595813..dfcee41 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -65,6 +65,8 @@ class HttpNetworkTransaction : public HttpTransaction,
const HttpResponseInfo& response_info,
HttpAuthController* auth_controller);
virtual void OnNeedsClientAuth(SSLCertRequestInfo* cert_info);
+ virtual void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
+ HttpStream* stream);
private:
FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, ResetStateForRestart);
@@ -135,11 +137,6 @@ class HttpNetworkTransaction : public HttpTransaction,
// Called to handle a client certificate request.
int HandleCertificateRequest(int error);
- // Called to possibly recover from an SSL handshake error. Sets next_state_
- // and returns OK if recovering from the error. Otherwise, the same error
- // code is returned.
- int HandleSSLHandshakeError(int error);
-
// Called to possibly recover from the given error. Sets next_state_ and
// returns OK if recovering from the error. Otherwise, the same error code
// is returned.
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index b9acbfc..260de13 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -20,7 +20,6 @@
#include "net/base/net_log.h"
#include "net/base/net_log_unittest.h"
#include "net/base/request_priority.h"
-#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/base/ssl_info.h"
#include "net/base/test_completion_callback.h"
@@ -75,6 +74,7 @@ struct SessionDependencies {
// Default set of dependencies -- "null" proxy service.
SessionDependencies()
: host_resolver(new MockHostResolver),
+ cert_verifier(new CertVerifier),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
@@ -84,6 +84,7 @@ struct SessionDependencies {
// Custom proxy service dependency.
explicit SessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
+ cert_verifier(new CertVerifier),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
@@ -91,6 +92,7 @@ struct SessionDependencies {
net_log(NULL) {}
scoped_ptr<MockHostResolverBase> host_resolver;
+ scoped_ptr<CertVerifier> cert_verifier;
scoped_refptr<ProxyService> proxy_service;
scoped_refptr<SSLConfigService> ssl_config_service;
MockClientSocketFactory socket_factory;
@@ -100,6 +102,7 @@ struct SessionDependencies {
HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
return new HttpNetworkSession(session_deps->host_resolver.get(),
+ session_deps->cert_verifier.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -175,15 +178,18 @@ class HttpNetworkTransactionTest : public PlatformTest {
rv = ReadTransaction(trans.get(), &out.response_data);
EXPECT_EQ(OK, rv);
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
- log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
+ entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
- log.entries(), pos,
+ entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
- CapturingNetLog::Entry entry = log.entries()[pos];
+ CapturingNetLog::Entry entry = entries[pos];
NetLogHttpRequestParameter* request_params =
static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
@@ -308,7 +314,8 @@ CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
template<>
CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
HttpNetworkSession* session)
- : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
+ : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
+ session->cert_verifier(), NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
//-----------------------------------------------------------------------------
@@ -1526,11 +1533,13 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
- log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
+ entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
- log.entries(), pos,
+ entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
@@ -1630,11 +1639,13 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
- log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
+ entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
- log.entries(), pos,
+ entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
@@ -1832,11 +1843,13 @@ TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
rv = callback1.WaitForResult();
EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
- log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
+ entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
- log.entries(), pos,
+ entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
}
@@ -2267,10 +2280,11 @@ TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback1.WaitForResult();
- EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
+ EXPECT_EQ(OK, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
- ASSERT_TRUE(response == NULL);
+ ASSERT_FALSE(response == NULL);
+ EXPECT_EQ(500, response->headers->response_code());
}
// Test the challenge-response-retry sequence through an HTTPS Proxy
@@ -4458,6 +4472,238 @@ TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
}
+// Test an HTTPS Proxy's ability to redirect a CONNECT request
+TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
+ SessionDependencies session_deps(
+ ProxyService::CreateFixed("https://proxy:70"));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
+ MockWrite data_writes[] = {
+ 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"),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 302 Redirect\r\n"),
+ MockRead("Location: http://login.example.com/\r\n"),
+ MockRead("Content-Length: 0\r\n\r\n"),
+ MockRead(false, OK),
+ };
+
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads),
+ data_writes, arraysize(data_writes));
+ SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
+
+ session_deps.socket_factory.AddSocketDataProvider(&data);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
+
+ TestCompletionCallback callback;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
+ int rv = trans->Start(&request, &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_EQ(302, response->headers->response_code());
+ std::string url;
+ EXPECT_TRUE(response->headers->IsRedirect(&url));
+ EXPECT_EQ("http://login.example.com/", url);
+}
+
+// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
+TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
+ SessionDependencies session_deps(
+ ProxyService::CreateFixed("https://proxy:70"));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
+ scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
+ MockWrite data_writes[] = {
+ CreateMockWrite(*conn.get(), 0, false),
+ };
+
+ static const char* const kExtraHeaders[] = {
+ "location",
+ "http://login.example.com/",
+ };
+ scoped_ptr<spdy::SpdyFrame> resp(
+ ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
+ arraysize(kExtraHeaders)/2, 1));
+ MockRead data_reads[] = {
+ CreateMockRead(*resp.get(), 1, false),
+ MockRead(true, 0, 2), // EOF
+ };
+
+ scoped_refptr<DelayedSocketData> data(
+ new DelayedSocketData(
+ 1, // wait for one write to finish before reading.
+ data_reads, arraysize(data_reads),
+ data_writes, arraysize(data_writes)));
+ SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
+ proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
+ proxy_ssl.next_proto = "spdy/2";
+ proxy_ssl.was_npn_negotiated = true;
+
+ session_deps.socket_factory.AddSocketDataProvider(data.get());
+ session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
+
+ TestCompletionCallback callback;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
+ int rv = trans->Start(&request, &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_EQ(302, response->headers->response_code());
+ std::string url;
+ EXPECT_TRUE(response->headers->IsRedirect(&url));
+ EXPECT_EQ("http://login.example.com/", url);
+}
+
+// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
+TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
+ SessionDependencies session_deps(
+ ProxyService::CreateFixed("https://proxy:70"));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
+ MockWrite data_writes[] = {
+ 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"),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 404 Not Found\r\n"),
+ MockRead("Content-Length: 23\r\n\r\n"),
+ MockRead("The host does not exist"),
+ MockRead(false, OK),
+ };
+
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads),
+ data_writes, arraysize(data_writes));
+ SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
+
+ session_deps.socket_factory.AddSocketDataProvider(&data);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
+
+ TestCompletionCallback callback;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
+ int rv = trans->Start(&request, &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_EQ(404, response->headers->response_code());
+ EXPECT_EQ(23, response->headers->GetContentLength());
+ EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
+ EXPECT_FALSE(response->ssl_info.is_valid());
+
+ std::string response_data;
+ ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
+ EXPECT_EQ("The host does not exist", response_data);
+}
+
+// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
+// request
+TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
+ SessionDependencies session_deps(
+ ProxyService::CreateFixed("https://proxy:70"));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.google.com/");
+ request.load_flags = 0;
+
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
+ scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
+ MockWrite data_writes[] = {
+ CreateMockWrite(*conn.get(), 0, false),
+ };
+
+ static const char* const kExtraHeaders[] = {
+ "location",
+ "http://login.example.com/",
+ };
+ scoped_ptr<spdy::SpdyFrame> resp(
+ ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
+ arraysize(kExtraHeaders)/2, 1));
+ scoped_ptr<spdy::SpdyFrame> body(
+ ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
+ MockRead data_reads[] = {
+ CreateMockRead(*resp.get(), 1, false),
+ CreateMockRead(*body.get(), 2, false),
+ MockRead(true, 0, 3), // EOF
+ };
+
+ scoped_refptr<DelayedSocketData> data(
+ new DelayedSocketData(
+ 1, // wait for one write to finish before reading.
+ data_reads, arraysize(data_reads),
+ data_writes, arraysize(data_writes)));
+ SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
+ proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
+ proxy_ssl.next_proto = "spdy/2";
+ proxy_ssl.was_npn_negotiated = true;
+
+ session_deps.socket_factory.AddSocketDataProvider(data.get());
+ session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
+
+ TestCompletionCallback callback;
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(CreateSession(&session_deps)));
+
+ int rv = trans->Start(&request, &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+
+ ASSERT_FALSE(response == NULL);
+
+ EXPECT_EQ(404, response->headers->response_code());
+ EXPECT_FALSE(response->ssl_info.is_valid());
+
+ std::string response_data;
+ ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
+ EXPECT_EQ("The host does not exist", response_data);
+}
+
// Test HTTPS connections to a site with a bad certificate, going through an
// HTTPS proxy
TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
@@ -6465,6 +6711,10 @@ class CapturingProxyResolver : public ProxyResolver {
NOTREACHED();
}
+ virtual void CancelSetPacScript() {
+ NOTREACHED();
+ }
+
virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
CompletionCallback* /*callback*/) {
return OK;
@@ -6671,7 +6921,8 @@ TEST_F(HttpNetworkTransactionTest,
session->ssl_config_service()->GetSSLConfig(&ssl_config);
ClientSocket* socket = connection->release_socket();
socket = session->socket_factory()->CreateSSLClientSocket(
- socket, HostPortPair("" , 443), ssl_config, NULL /* ssl_host_info */);
+ socket, HostPortPair("" , 443), ssl_config, NULL /* ssl_host_info */,
+ session->cert_verifier());
connection->set_socket(socket);
EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
EXPECT_EQ(OK, callback.WaitForResult());
@@ -7725,11 +7976,13 @@ TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
- log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
+ entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
- log.entries(), pos,
+ entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
@@ -7787,11 +8040,13 @@ TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rv = callback1.WaitForResult();
EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
size_t pos = ExpectLogContainsSomewhere(
- log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
+ entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
NetLog::PHASE_NONE);
ExpectLogContainsSomewhere(
- log.entries(), pos,
+ entries, pos,
NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
NetLog::PHASE_NONE);
}
@@ -7952,303 +8207,4 @@ TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
EXPECT_EQ("hello world", contents);
}
-// Ensure that a client certificate is removed from the SSL client auth
-// cache when:
-// 1) No proxy is involved.
-// 2) TLS False Start is disabled.
-// 3) The initial TLS handshake requests a client certificate.
-// 4) The client supplies an invalid/unacceptable certificate.
-TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
- SessionDependencies session_deps;
-
- scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
- cert_request->host_and_port = "www.example.com:443";
-
- // [ssl_]data1 contains the data for the first SSL handshake. When a
- // CertificateRequest is received for the first time, the handshake will
- // be aborted to allow the caller to provide a certificate.
- SSLSocketDataProvider ssl_data1(true /* async */,
- net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
- ssl_data1.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
- net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data1);
-
- // [ssl_]data2 contains the data for the second SSL handshake. When TLS
- // False Start is not being used, the result of the SSL handshake will be
- // returned as part of the SSLClientSocket::Connect() call. This test
- // matches the result of a server sending a handshake_failure alert,
- // rather than a Finished message, because it requires a client
- // certificate and none was supplied.
- SSLSocketDataProvider ssl_data2(true /* async */,
- net::ERR_SSL_PROTOCOL_ERROR);
- ssl_data2.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
- net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data2);
-
- // [ssl_]data3 contains the data for the third SSL handshake. When a
- // connection to a server fails during an SSL handshake,
- // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
- // connection was attempted with TLSv1. This is transparent to the caller
- // of the HttpNetworkTransaction. Because this test failure is due to
- // requiring a client certificate, this fallback handshake should also
- // fail.
- SSLSocketDataProvider ssl_data3(true /* async */,
- net::ERR_SSL_PROTOCOL_ERROR);
- ssl_data3.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
- net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data3);
-
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
-
- net::HttpRequestInfo request_info;
- request_info.url = GURL("https://www.example.com/");
- request_info.method = "GET";
- request_info.load_flags = net::LOAD_NORMAL;
-
- // Begin the SSL handshake with the peer. This consumes ssl_data1.
- TestCompletionCallback callback;
- int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
- ASSERT_EQ(net::ERR_IO_PENDING, rv);
-
- // Complete the SSL handshake, which should abort due to requiring a
- // client certificate.
- rv = callback.WaitForResult();
- ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
-
- // Indicate that no certificate should be supplied. From the perspective
- // of SSLClientCertCache, NULL is just as meaningful as a real
- // certificate, so this is the same as supply a
- // legitimate-but-unacceptable certificate.
- rv = trans->RestartWithCertificate(NULL, &callback);
- ASSERT_EQ(net::ERR_IO_PENDING, rv);
-
- // Ensure the certificate was added to the client auth cache before
- // allowing the connection to continue restarting.
- scoped_refptr<X509Certificate> client_cert;
- ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
- ASSERT_EQ(NULL, client_cert.get());
-
- // Restart the handshake. This will consume ssl_data2, which fails, and
- // then consume ssl_data3, which should also fail. The result code is
- // checked against what ssl_data3 should return.
- rv = callback.WaitForResult();
- ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
-
- // Ensure that the client certificate is removed from the cache on a
- // handshake failure.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
-}
-
-// Ensure that a client certificate is removed from the SSL client auth
-// cache when:
-// 1) No proxy is involved.
-// 2) TLS False Start is enabled.
-// 3) The initial TLS handshake requests a client certificate.
-// 4) The client supplies an invalid/unacceptable certificate.
-TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
- SessionDependencies session_deps;
-
- scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
- cert_request->host_and_port = "www.example.com:443";
-
- // When TLS False Start is used, SSLClientSocket::Connect() calls will
- // return successfully after reading up to the peer's Certificate message.
- // This is to allow the caller to call SSLClientSocket::Write(), which can
- // enqueue application data to be sent in the same packet as the
- // ChangeCipherSpec and Finished messages.
- // The actual handshake will be finished when SSLClientSocket::Read() is
- // called, which expects to process the peer's ChangeCipherSpec and
- // Finished messages. If there was an error negotiating with the peer,
- // such as due to the peer requiring a client certificate when none was
- // supplied, the alert sent by the peer won't be processed until Read() is
- // called.
-
- // Like the non-False Start case, when a client certificate is requested by
- // the peer, the handshake is aborted during the Connect() call.
- // [ssl_]data1 represents the initial SSL handshake with the peer.
- SSLSocketDataProvider ssl_data1(true /* async */,
- net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
- ssl_data1.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
- net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data1);
-
- // When a client certificate is supplied, Connect() will not be aborted
- // when the peer requests the certificate. Instead, the handshake will
- // artificially succeed, allowing the caller to write the HTTP request to
- // the socket. The handshake messages are not processed until Read() is
- // called, which then detects that the handshake was aborted, due to the
- // peer sending a handshake_failure because it requires a client
- // certificate.
- SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
- ssl_data2.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
- net::MockRead data2_reads[] = {
- net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
- };
- net::StaticSocketDataProvider data2(
- data2_reads, arraysize(data2_reads), NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data2);
-
- // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
- // the data for the SSL handshake once the TLSv1 connection falls back to
- // SSLv3. It has the same behaviour as [ssl_]data2.
- SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
- ssl_data3.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
- net::StaticSocketDataProvider data3(
- data2_reads, arraysize(data2_reads), NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data3);
-
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
-
- net::HttpRequestInfo request_info;
- request_info.url = GURL("https://www.example.com/");
- request_info.method = "GET";
- request_info.load_flags = net::LOAD_NORMAL;
-
- // Begin the initial SSL handshake.
- TestCompletionCallback callback;
- int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
- ASSERT_EQ(net::ERR_IO_PENDING, rv);
-
- // Complete the SSL handshake, which should abort due to requiring a
- // client certificate.
- rv = callback.WaitForResult();
- ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
-
- // Indicate that no certificate should be supplied. From the perspective
- // of SSLClientCertCache, NULL is just as meaningful as a real
- // certificate, so this is the same as supply a
- // legitimate-but-unacceptable certificate.
- rv = trans->RestartWithCertificate(NULL, &callback);
- ASSERT_EQ(net::ERR_IO_PENDING, rv);
-
- // Ensure the certificate was added to the client auth cache before
- // allowing the connection to continue restarting.
- scoped_refptr<X509Certificate> client_cert;
- ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
- ASSERT_EQ(NULL, client_cert.get());
-
-
- // Restart the handshake. This will consume ssl_data2, which fails, and
- // then consume ssl_data3, which should also fail. The result code is
- // checked against what ssl_data3 should return.
- rv = callback.WaitForResult();
- ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
-
- // Ensure that the client certificate is removed from the cache on a
- // handshake failure.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
-}
-
-// Ensure that a client certificate is removed from the SSL client auth
-// cache when:
-// 1) An HTTPS proxy is involved.
-// 3) The HTTPS proxy requests a client certificate.
-// 4) The client supplies an invalid/unacceptable certificate for the
-// proxy.
-// The test is repeated twice, first for connecting to an HTTPS endpoint,
-// then for connecting to an HTTP endpoint.
-TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
- SessionDependencies session_deps(
- ProxyService::CreateFixed("https://proxy:70"));
- CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
- session_deps.net_log = log.bound().net_log();
-
- scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
- cert_request->host_and_port = "proxy:70";
-
- // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
- // [ssl_]data[1-3]. Rather than represending the endpoint
- // (www.example.com:443), they represent failures with the HTTPS proxy
- // (proxy:70).
- SSLSocketDataProvider ssl_data1(true /* async */,
- net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
- ssl_data1.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
- net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data1);
-
- SSLSocketDataProvider ssl_data2(true /* async */,
- net::ERR_SSL_PROTOCOL_ERROR);
- ssl_data2.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
- net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data2);
-
- SSLSocketDataProvider ssl_data3(true /* async */,
- net::ERR_SSL_PROTOCOL_ERROR);
- ssl_data3.cert_request_info = cert_request.get();
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
- net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data3);
-
- net::HttpRequestInfo requests[2];
- requests[0].url = GURL("https://www.example.com/");
- requests[0].method = "GET";
- requests[0].load_flags = net::LOAD_NORMAL;
-
- requests[1].url = GURL("http://www.example.com/");
- requests[1].method = "GET";
- requests[1].load_flags = net::LOAD_NORMAL;
-
- for (size_t i = 0; i < arraysize(requests); ++i) {
- session_deps.socket_factory.ResetNextMockIndexes();
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
- scoped_ptr<HttpNetworkTransaction> trans(
- new HttpNetworkTransaction(session));
-
- // Begin the SSL handshake with the proxy.
- TestCompletionCallback callback;
- int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
- ASSERT_EQ(net::ERR_IO_PENDING, rv);
-
- // Complete the SSL handshake, which should abort due to requiring a
- // client certificate.
- rv = callback.WaitForResult();
- ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
-
- // Indicate that no certificate should be supplied. From the perspective
- // of SSLClientCertCache, NULL is just as meaningful as a real
- // certificate, so this is the same as supply a
- // legitimate-but-unacceptable certificate.
- rv = trans->RestartWithCertificate(NULL, &callback);
- ASSERT_EQ(net::ERR_IO_PENDING, rv);
-
- // Ensure the certificate was added to the client auth cache before
- // allowing the connection to continue restarting.
- scoped_refptr<X509Certificate> client_cert;
- ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
- &client_cert));
- ASSERT_EQ(NULL, client_cert.get());
- // Ensure the certificate was NOT cached for the endpoint. This only
- // applies to HTTPS requests, but is fine to check for HTTP requests.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
-
- // Restart the handshake. This will consume ssl_data2, which fails, and
- // then consume ssl_data3, which should also fail. The result code is
- // checked against what ssl_data3 should return.
- rv = callback.WaitForResult();
- ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
-
- // Now that the new handshake has failed, ensure that the client
- // certificate was removed from the client auth cache.
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
- &client_cert));
- ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
- &client_cert));
- }
-}
-
} // namespace net
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index 1ff325c..efff248 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -12,6 +12,7 @@
#include "net/base/io_buffer.h"
#include "net/base/net_log.h"
#include "net/base/net_util.h"
+#include "net/http/http_basic_stream.h"
#include "net/http/http_net_log_params.h"
#include "net/http/http_network_session.h"
#include "net/http/http_proxy_utils.h"
@@ -31,7 +32,8 @@ HttpProxyClientSocket::HttpProxyClientSocket(
HttpAuthCache* http_auth_cache,
HttpAuthHandlerFactory* http_auth_handler_factory,
bool tunnel,
- bool using_spdy)
+ bool using_spdy,
+ bool is_https_proxy)
: ALLOW_THIS_IN_INITIALIZER_LIST(
io_callback_(this, &HttpProxyClientSocket::OnIOComplete)),
next_state_(STATE_NONE),
@@ -46,6 +48,7 @@ HttpProxyClientSocket::HttpProxyClientSocket(
: NULL),
tunnel_(tunnel),
using_spdy_(using_spdy),
+ is_https_proxy_(is_https_proxy),
net_log_(transport_socket->socket()->NetLog()) {
// Synthesize the bits of a request that we actually use.
request_.url = request_url;
@@ -59,6 +62,7 @@ HttpProxyClientSocket::~HttpProxyClientSocket() {
Disconnect();
}
+<<<<<<< HEAD
#ifdef ANDROID
// TODO(kristianm): handle the case when wait_for_connect is true
// (sync requests)
@@ -68,6 +72,15 @@ int HttpProxyClientSocket::Connect(CompletionCallback* callback
, bool wait_for_connect
#endif
) {
+=======
+HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() {
+ return new HttpBasicStream(transport_.release(),
+ http_stream_parser_.release(), false);
+}
+
+
+int HttpProxyClientSocket::Connect(CompletionCallback* callback) {
+>>>>>>> chromium.org at r10.0.621.0
DCHECK(transport_.get());
DCHECK(transport_->socket());
DCHECK(!user_callback_);
@@ -153,7 +166,8 @@ void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
}
void HttpProxyClientSocket::Disconnect() {
- transport_->socket()->Disconnect();
+ if (transport_.get())
+ transport_->socket()->Disconnect();
// Reset other states to make sure they aren't mistakenly used later.
// These are the states initialized by Connect().
@@ -170,6 +184,10 @@ bool HttpProxyClientSocket::IsConnectedAndIdle() const {
transport_->socket()->IsConnectedAndIdle();
}
+const BoundNetLog& HttpProxyClientSocket::NetLog() const {
+ return net_log_;
+}
+
void HttpProxyClientSocket::SetSubresourceSpeculation() {
if (transport_.get() && transport_->socket()) {
transport_->socket()->SetSubresourceSpeculation();
@@ -413,6 +431,8 @@ int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
return HandleAuthChallenge();
default:
+ if (is_https_proxy_)
+ return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
// For all other status codes, we conservatively fail the CONNECT
// request.
// We lose something by doing this. We have seen proxy 403, 404, and
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index 335f930..ef53c2d 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -17,7 +17,7 @@
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_info.h"
-#include "net/socket/client_socket.h"
+#include "net/http/proxy_client_socket.h"
class GURL;
@@ -32,7 +32,7 @@ class HttpStream;
class HttpStreamParser;
class IOBuffer;
-class HttpProxyClientSocket : public ClientSocket {
+class HttpProxyClientSocket : public ProxyClientSocket {
public:
// Takes ownership of |transport_socket|, which should already be connected
// by the time Connect() is called. If tunnel is true then on Connect()
@@ -45,7 +45,8 @@ class HttpProxyClientSocket : public ClientSocket {
HttpAuthCache* http_auth_cache,
HttpAuthHandlerFactory* http_auth_handler_factory,
bool tunnel,
- bool using_spdy);
+ bool using_spdy,
+ bool is_https_proxy);
// On destruction Disconnect() is called.
virtual ~HttpProxyClientSocket();
@@ -55,10 +56,12 @@ class HttpProxyClientSocket : public ClientSocket {
// RestartWithAuth.
int RestartWithAuth(CompletionCallback* callback);
- const HttpResponseInfo* GetResponseInfo() const {
+ const HttpResponseInfo* GetConnectResponseInfo() const {
return response_.headers ? &response_ : NULL;
}
+ virtual HttpStream* CreateConnectResponseStream();
+
const scoped_refptr<HttpAuthController>& auth_controller() {
return auth_;
}
@@ -78,7 +81,7 @@ class HttpProxyClientSocket : public ClientSocket {
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
- virtual const BoundNetLog& NetLog() const { return net_log_; }
+ virtual const BoundNetLog& NetLog() const;
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
@@ -150,7 +153,7 @@ class HttpProxyClientSocket : public ClientSocket {
scoped_refptr<IOBuffer> drain_buf_;
// Stores the underlying socket.
- const scoped_ptr<ClientSocketHandle> transport_;
+ scoped_ptr<ClientSocketHandle> transport_;
// The hostname and port of the endpoint. This is not necessarily the one
// specified by the URL, due to Alternate-Protocol or fixed testing ports.
@@ -159,6 +162,8 @@ class HttpProxyClientSocket : public ClientSocket {
const bool tunnel_;
// If true, then the connection to the proxy is a SPDY connection.
const bool using_spdy_;
+ // If true, then SSL is used to communicate with this proxy
+ const bool is_https_proxy_;
std::string request_line_;
HttpRequestHeaders request_headers_;
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index 119321a..4680bb1 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -334,17 +334,25 @@ int HttpProxyConnectJob::DoHttpProxyConnect() {
params_->http_auth_cache(),
params_->http_auth_handler_factory(),
params_->tunnel(),
+<<<<<<< HEAD
using_spdy_));
return transport_socket_->Connect(&callback_
#ifdef ANDROID
, false
#endif
);
+=======
+ using_spdy_,
+ params_->ssl_params() != NULL));
+ return transport_socket_->Connect(&callback_);
+>>>>>>> chromium.org at r10.0.621.0
}
int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
- if (result == OK || result == ERR_PROXY_AUTH_REQUESTED)
+ if (result == OK || result == ERR_PROXY_AUTH_REQUESTED ||
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
set_socket(transport_socket_.release());
+ }
return result;
}
@@ -442,6 +450,10 @@ void HttpProxyClientSocketPool::CloseIdleSockets() {
base_.CloseIdleSockets();
}
+int HttpProxyClientSocketPool::IdleSocketCount() const {
+ return base_.idle_socket_count();
+}
+
int HttpProxyClientSocketPool::IdleSocketCountInGroup(
const std::string& group_name) const {
return base_.IdleSocketCountInGroup(group_name);
@@ -474,4 +486,12 @@ DictionaryValue* HttpProxyClientSocketPool::GetInfoAsValue(
return dict;
}
+base::TimeDelta HttpProxyClientSocketPool::ConnectionTimeout() const {
+ return base_.ConnectionTimeout();
+}
+
+ClientSocketPoolHistograms* HttpProxyClientSocketPool::histograms() const {
+ return base_.histograms();
+}
+
} // namespace net
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h
index a6ef0b8..39a8896 100644
--- a/net/http/http_proxy_client_socket_pool.h
+++ b/net/http/http_proxy_client_socket_pool.h
@@ -15,6 +15,7 @@
#include "net/base/host_port_pair.h"
#include "net/http/http_auth.h"
#include "net/http/http_response_info.h"
+#include "net/http/proxy_client_socket.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/client_socket_pool.h"
@@ -163,7 +164,7 @@ class HttpProxyConnectJob : public ConnectJob {
State next_state_;
CompletionCallbackImpl<HttpProxyConnectJob> callback_;
scoped_ptr<ClientSocketHandle> transport_socket_handle_;
- scoped_ptr<ClientSocket> transport_socket_;
+ scoped_ptr<ProxyClientSocket> transport_socket_;
bool using_spdy_;
HttpResponseInfo error_response_info_;
@@ -210,9 +211,7 @@ class HttpProxyClientSocketPool : public ClientSocketPool {
virtual void CloseIdleSockets();
- virtual int IdleSocketCount() const {
- return base_.idle_socket_count();
- }
+ virtual int IdleSocketCount() const;
virtual int IdleSocketCountInGroup(const std::string& group_name) const;
@@ -223,13 +222,9 @@ class HttpProxyClientSocketPool : public ClientSocketPool {
const std::string& type,
bool include_nested_pools) const;
- virtual base::TimeDelta ConnectionTimeout() const {
- return base_.ConnectionTimeout();
- }
+ virtual base::TimeDelta ConnectionTimeout() const;
- virtual ClientSocketPoolHistograms* histograms() const {
- return base_.histograms();
- };
+ virtual ClientSocketPoolHistograms* histograms() const;
private:
typedef ClientSocketPoolBase<HttpProxySocketParams> PoolBase;
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 56fae19..8c6d545 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -62,9 +62,11 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
ssl_histograms_("MockSSL"),
ssl_config_service_(new SSLConfigServiceDefaults),
host_resolver_(new MockHostResolver),
+ cert_verifier_(new CertVerifier),
ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup,
&ssl_histograms_,
host_resolver_.get(),
+ cert_verifier_.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -77,6 +79,7 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
http_auth_handler_factory_(
HttpAuthHandlerFactory::CreateDefault(host_resolver_.get())),
session_(new HttpNetworkSession(host_resolver_.get(),
+ cert_verifier_.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -192,6 +195,7 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
ClientSocketPoolHistograms ssl_histograms_;
scoped_refptr<SSLConfigService> ssl_config_service_;
scoped_ptr<HostResolver> host_resolver_;
+ scoped_ptr<CertVerifier> cert_verifier_;
SSLClientSocketPool ssl_socket_pool_;
scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
@@ -498,9 +502,18 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
data_->RunFor(2);
- EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
- EXPECT_FALSE(handle_.is_initialized());
- EXPECT_FALSE(handle_.socket());
+ rv = callback_.WaitForResult();
+ if (GetParam() == HTTP) {
+ // HTTP Proxy CONNECT responses are not trustworthy
+ EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
+ EXPECT_FALSE(handle_.is_initialized());
+ EXPECT_FALSE(handle_.socket());
+ } else {
+ // HTTPS or SPDY Proxy CONNECT responses are trustworthy
+ EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
+ EXPECT_TRUE(handle_.is_initialized());
+ EXPECT_TRUE(handle_.socket());
+ }
}
// It would be nice to also test the timeouts in HttpProxyClientSocketPool.
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index 75f099a..76304f8 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -178,6 +178,7 @@ class HttpResponseBodyDrainerTest : public testing::Test {
NULL /* host_resolver */,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
+ NULL,
NULL /* ssl_host_info_factory */,
ProxyService::CreateDirect(),
NULL,
diff --git a/net/http/http_stream_factory.h b/net/http/http_stream_factory.h
index dceb00b..c5a0dc3 100644
--- a/net/http/http_stream_factory.h
+++ b/net/http/http_stream_factory.h
@@ -48,8 +48,8 @@ class HttpStreamFactory : public StreamFactory,
const BoundNetLog& net_log,
CompletionCallback* callback);
- void AddTLSIntolerantServer(const GURL& url);
- bool IsTLSIntolerantServer(const GURL& url);
+ virtual void AddTLSIntolerantServer(const GURL& url);
+ virtual bool IsTLSIntolerantServer(const GURL& url);
virtual void ProcessAlternateProtocol(
HttpAlternateProtocols* alternate_protocols,
@@ -66,6 +66,8 @@ class HttpStreamFactory : public StreamFactory,
// Turns spdy on or off.
static void set_spdy_enabled(bool value) {
spdy_enabled_ = value;
+ if (value == false)
+ set_next_protos("");
}
static bool spdy_enabled() { return spdy_enabled_; }
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 63fce33..646f79c 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/basictypes.h"
+#include "net/base/cert_verifier.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_log.h"
#include "net/base/ssl_config_service_defaults.h"
@@ -27,6 +28,7 @@ struct SessionDependencies {
// Custom proxy service dependency.
explicit SessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
+ cert_verifier(new CertVerifier),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
http_auth_handler_factory(
@@ -34,6 +36,7 @@ struct SessionDependencies {
net_log(NULL) {}
scoped_ptr<MockHostResolverBase> host_resolver;
+ scoped_ptr<CertVerifier> cert_verifier;
scoped_refptr<ProxyService> proxy_service;
scoped_refptr<SSLConfigService> ssl_config_service;
MockClientSocketFactory socket_factory;
@@ -43,6 +46,7 @@ struct SessionDependencies {
HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
return new HttpNetworkSession(session_deps->host_resolver.get(),
+ session_deps->cert_verifier.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -170,7 +174,8 @@ CapturePreconnectsHttpProxySocketPool::CapturePreconnectsSocketPool(
template<>
CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool(
HttpNetworkSession* session)
- : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
+ : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
+ session->cert_verifier(), NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
TEST(HttpStreamFactoryTest, PreconnectDirect) {
diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc
index fbe4a32..8f4c9b1 100644
--- a/net/http/http_stream_request.cc
+++ b/net/http/http_stream_request.cc
@@ -63,6 +63,7 @@ HttpStreamRequest::HttpStreamRequest(
force_spdy_always_(HttpStreamFactory::force_spdy_always()),
force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()),
spdy_certificate_error_(OK),
+ alternate_protocol_(HttpAlternateProtocols::UNINITIALIZED),
establishing_tunnel_(false),
was_alternate_protocol_available_(false),
was_npn_negotiated_(false),
@@ -147,6 +148,18 @@ LoadState HttpStreamRequest::GetLoadState() const {
}
}
+bool HttpStreamRequest::was_alternate_protocol_available() const {
+ return was_alternate_protocol_available_;
+}
+
+bool HttpStreamRequest::was_npn_negotiated() const {
+ return was_npn_negotiated_;
+}
+
+bool HttpStreamRequest::using_spdy() const {
+ return using_spdy_;
+}
+
void HttpStreamRequest::GetSSLInfo() {
DCHECK(using_ssl_);
DCHECK(!establishing_tunnel_);
@@ -193,6 +206,12 @@ void HttpStreamRequest::OnNeedsClientAuthCallback(
delegate_->OnNeedsClientAuth(cert_info);
}
+void HttpStreamRequest::OnHttpsProxyTunnelResponseCallback(
+ const HttpResponseInfo& response_info,
+ HttpStream* stream) {
+ delegate_->OnHttpsProxyTunnelResponse(response_info, stream);
+}
+
void HttpStreamRequest::OnPreconnectsComplete(int result) {
preconnect_delegate_->OnPreconnectsComplete(this, result);
}
@@ -240,7 +259,7 @@ int HttpStreamRequest::RunLoop(int result) {
HttpProxyClientSocket* http_proxy_socket =
static_cast<HttpProxyClientSocket*>(connection_->socket());
const HttpResponseInfo* tunnel_auth_response =
- http_proxy_socket->GetResponseInfo();
+ http_proxy_socket->GetConnectResponseInfo();
next_state_ = STATE_WAITING_USER_ACTION;
MessageLoop::current()->PostTask(
@@ -260,6 +279,23 @@ int HttpStreamRequest::RunLoop(int result) {
connection_->ssl_error_response_info().cert_request_info));
return ERR_IO_PENDING;
+ case ERR_HTTPS_PROXY_TUNNEL_RESPONSE:
+ {
+ DCHECK(connection_.get());
+ DCHECK(connection_->socket());
+ DCHECK(establishing_tunnel_);
+
+ ProxyClientSocket* proxy_socket =
+ static_cast<ProxyClientSocket*>(connection_->socket());
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &HttpStreamRequest::OnHttpsProxyTunnelResponseCallback,
+ *proxy_socket->GetConnectResponseInfo(),
+ proxy_socket->CreateConnectResponseStream()));
+ return ERR_IO_PENDING;
+ }
+
case OK:
next_state_ = STATE_DONE;
MessageLoop::current()->PostTask(
@@ -657,13 +693,15 @@ int HttpStreamRequest::DoInitConnectionComplete(int result) {
if (!force_spdy_over_ssl_ && force_spdy_always_)
SwitchToSpdyMode();
- if (result == ERR_PROXY_AUTH_REQUESTED) {
+ if (result == ERR_PROXY_AUTH_REQUESTED ||
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
DCHECK(!ssl_started);
// Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
// SSL socket, but there was an error before that could happen. This
// puts the in progress HttpProxy socket into |connection_| in order to
- // complete the auth. The tunnel restart code is careful to remove it
- // before returning control to the rest of this class.
+ // complete the auth (or read the response body). The tunnel restart code
+ // is careful to remove it before returning control to the rest of this
+ // class.
connection_.reset(connection_->release_pending_http_proxy_connection());
return result;
}
@@ -709,7 +747,7 @@ int HttpStreamRequest::DoInitConnectionComplete(int result) {
}
}
if (result < 0)
- return result;
+ return HandleSSLHandshakeError(result);
}
next_state_ = STATE_CREATE_STREAM;
@@ -739,7 +777,8 @@ int HttpStreamRequest::DoCreateStream() {
if (!using_spdy_) {
bool using_proxy = (proxy_info()->is_http() || proxy_info()->is_https()) &&
request_info().url.SchemeIs("http");
- stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
+ stream_.reset(new HttpBasicStream(connection_.release(), NULL,
+ using_proxy));
return OK;
}
@@ -787,8 +826,8 @@ int HttpStreamRequest::DoCreateStream() {
if (spdy_session->IsClosed())
return ERR_CONNECTION_CLOSED;
- bool useRelativeUrl = direct || request_info().url.SchemeIs("https");
- stream_.reset(new SpdyHttpStream(spdy_session, useRelativeUrl));
+ bool use_relative_url = direct || request_info().url.SchemeIs("https");
+ stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url));
return OK;
}
@@ -856,18 +895,6 @@ scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSSLParams(
ssl_config()->tls1_enabled = false;
}
- if (proxy_info()->is_https() && ssl_config()->send_client_cert) {
- // When connecting through an HTTPS proxy, disable TLS False Start so
- // that client authentication errors can be distinguished between those
- // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and
- // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR /
- // ERR_BAD_SSL_CLIENT_AUTH_CERT).
- // TODO(rch): This assumes that the HTTPS proxy will only request a
- // client certificate during the initial handshake.
- // http://crbug.com/FIXME
- ssl_config()->false_start_enabled = false;
- }
-
UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
static_cast<int>(ssl_config()->ssl3_fallback), 2);
@@ -956,11 +983,6 @@ int HttpStreamRequest::ReconsiderProxyAfterError(int error) {
return error;
}
- if (proxy_info()->is_https() && ssl_config_->send_client_cert) {
- session_->ssl_client_auth_cache()->Remove(
- proxy_info()->proxy_server().host_port_pair().ToString());
- }
-
int rv = session_->proxy_service()->ReconsiderProxyAfterError(
request_info().url, proxy_info(), &io_callback_, &pac_request_,
net_log_);
@@ -1007,6 +1029,35 @@ int HttpStreamRequest::HandleCertificateError(int error) {
return error;
}
+int HttpStreamRequest::HandleSSLHandshakeError(int error) {
+ if (ssl_config()->send_client_cert &&
+ (error == ERR_SSL_PROTOCOL_ERROR ||
+ error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
+ session_->ssl_client_auth_cache()->Remove(
+ GetHostAndPort(request_info().url));
+ }
+
+ switch (error) {
+ case ERR_SSL_PROTOCOL_ERROR:
+ case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
+ case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
+ case ERR_SSL_BAD_RECORD_MAC_ALERT:
+ if (ssl_config()->tls1_enabled &&
+ !SSLConfigService::IsKnownStrictTLSServer(
+ request_info().url.host())) {
+ // This could be a TLS-intolerant server, an SSL 3.0 server that
+ // chose a TLS-only cipher suite or a server with buggy DEFLATE
+ // support. Turn off TLS 1.0, DEFLATE support and retry.
+ factory_->AddTLSIntolerantServer(request_info().url);
+ next_state_ = STATE_INIT_CONNECTION;
+ DCHECK(!connection_.get() || !connection_->socket());
+ error = OK;
+ }
+ break;
+ }
+ return error;
+}
+
void HttpStreamRequest::SwitchToSpdyMode() {
if (HttpStreamFactory::spdy_enabled())
using_spdy_ = true;
diff --git a/net/http/http_stream_request.h b/net/http/http_stream_request.h
index c07dc1c..f20b5f3 100644
--- a/net/http/http_stream_request.h
+++ b/net/http/http_stream_request.h
@@ -69,11 +69,9 @@ class HttpStreamRequest : public StreamRequest {
const string16& password);
virtual LoadState GetLoadState() const;
- virtual bool was_alternate_protocol_available() const {
- return was_alternate_protocol_available_;
- }
- virtual bool was_npn_negotiated() const { return was_npn_negotiated_; }
- virtual bool using_spdy() const { return using_spdy_; }
+ virtual bool was_alternate_protocol_available() const;
+ virtual bool was_npn_negotiated() const;
+ virtual bool using_spdy() const;
private:
enum AlternateProtocolMode {
@@ -109,6 +107,8 @@ class HttpStreamRequest : public StreamRequest {
void OnNeedsProxyAuthCallback(const HttpResponseInfo& response_info,
HttpAuthController* auth_controller);
void OnNeedsClientAuthCallback(SSLCertRequestInfo* cert_info);
+ void OnHttpsProxyTunnelResponseCallback(const HttpResponseInfo& response_info,
+ HttpStream* stream);
void OnPreconnectsComplete(int result);
void OnIOComplete(int result);
@@ -172,6 +172,11 @@ class HttpStreamRequest : public StreamRequest {
// Called to handle a client certificate request.
int HandleCertificateRequest(int error);
+ // Called to possibly recover from an SSL handshake error. Sets next_state_
+ // and returns OK if recovering from the error. Otherwise, the same error
+ // code is returned.
+ int HandleSSLHandshakeError(int error);
+
// Moves this stream request into SPDY mode.
void SwitchToSpdyMode();
diff --git a/net/http/proxy_client_socket.h b/net/http/proxy_client_socket.h
new file mode 100644
index 0000000..6557c88
--- /dev/null
+++ b/net/http/proxy_client_socket.h
@@ -0,0 +1,35 @@
+// 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_HTTP_PROXY_CLIENT_SOCKET_H_
+#define NET_HTTP_PROXY_CLIENT_SOCKET_H_
+#pragma once
+
+#include "net/socket/client_socket.h"
+
+namespace net {
+
+class HttpStream;
+class HttpResponseInfo;
+
+class ProxyClientSocket : public ClientSocket {
+ public:
+ ProxyClientSocket() {}
+ virtual ~ProxyClientSocket() {}
+
+ // Returns the HttpResponseInfo (including HTTP Headers) from
+ // the response to the CONNECT request.
+ virtual const HttpResponseInfo* GetConnectResponseInfo() const = 0;
+
+ // Transfers ownership of a newly created HttpStream to the caller
+ // which can be used to read the response body.
+ virtual HttpStream* CreateConnectResponseStream() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProxyClientSocket);
+};
+
+} // namespace net
+
+#endif // NET_HTTP_PROXY_CLIENT_SOCKET_H_
diff --git a/net/http/stream_factory.h b/net/http/stream_factory.h
index 94b3cc8..1a7aa77 100644
--- a/net/http/stream_factory.h
+++ b/net/http/stream_factory.h
@@ -69,6 +69,13 @@ class StreamRequest {
// may take a reference if it needs the cert_info beyond the lifetime of
// this callback.
virtual void OnNeedsClientAuth(SSLCertRequestInfo* cert_info) = 0;
+
+ // This is the failure of the CONNECT request through an HTTPS proxy.
+ // Headers can be read from |response_info|, while the body can be read
+ // from |stream|.
+ // Ownership of |stream| is transferred to the delegate.
+ virtual void OnHttpsProxyTunnelResponse(
+ const HttpResponseInfo& response_info, HttpStream* stream) = 0;
};
virtual ~StreamRequest() {}
diff --git a/net/net.gyp b/net/net.gyp
index a5134da..09b6267 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -29,6 +29,8 @@
'base/address_list_net_log_param.h',
'base/auth.cc',
'base/auth.h',
+ 'base/bandwidth_metrics.cc',
+ 'base/bandwidth_metrics.h',
'base/cache_type.h',
'base/capturing_net_log.cc',
'base/capturing_net_log.h',
@@ -76,8 +78,6 @@
'base/file_stream_win.cc',
'base/filter.cc',
'base/filter.h',
- 'base/forwarding_net_log.cc',
- 'base/forwarding_net_log.h',
'base/gzip_filter.cc',
'base/gzip_filter.h',
'base/gzip_header.cc',
@@ -142,6 +142,8 @@
'base/network_config_watcher_mac.h',
'base/nss_memio.c',
'base/nss_memio.h',
+ 'base/openssl_memory_private_key_store.cc',
+ 'base/openssl_private_key_store.h',
'base/pem_tokenizer.cc',
'base/pem_tokenizer.h',
'base/platform_mime_util.h',
@@ -175,6 +177,12 @@
'base/ssl_info.h',
'base/static_cookie_policy.cc',
'base/static_cookie_policy.h',
+ 'base/test_root_certs.cc',
+ 'base/test_root_certs.h',
+ 'base/test_root_certs_mac.cc',
+ 'base/test_root_certs_nss.cc',
+ 'base/test_root_certs_openssl.cc',
+ 'base/test_root_certs_win.cc',
'base/transport_security_state.cc',
'base/transport_security_state.h',
'base/sys_addrinfo.h',
@@ -237,7 +245,7 @@
'conditions': [
['use_openssl==1', {
'dependencies': [
- '../build/linux/system.gyp:openssl',
+ '../third_party/openssl/openssl.gyp:openssl',
],
}, { # else: not using openssl. Use NSS.
'dependencies': [
@@ -250,6 +258,7 @@
'sources!': [
'base/cert_database_nss.cc',
'base/keygen_handler_nss.cc',
+ 'base/test_root_certs_nss.cc',
'base/x509_certificate_nss.cc',
'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
'third_party/mozilla_security_manager/nsKeygenHandler.h',
@@ -270,6 +279,7 @@
'base/keygen_handler_nss.cc',
'base/nss_memio.c',
'base/nss_memio.h',
+ 'base/test_root_certs_nss.cc',
'base/x509_certificate_nss.cc',
'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
'third_party/mozilla_security_manager/nsKeygenHandler.h',
@@ -285,6 +295,9 @@
'sources!': [
'base/cert_database_openssl.cc',
'base/keygen_handler_openssl.cc',
+ 'base/openssl_memory_private_key_store.cc',
+ 'base/openssl_private_key_store.h',
+ 'base/test_root_certs_openssl.cc',
'base/x509_certificate_openssl.cc',
'base/x509_openssl_util.cc',
'base/x509_openssl_util.h',
@@ -334,7 +347,6 @@
'../third_party/zlib/zlib.gyp:zlib',
'net_base',
'net_resources',
- 'ssl_host_info',
],
'sources': [
'disk_cache/addr.cc',
@@ -400,12 +412,8 @@
'ftp/ftp_directory_listing_buffer.h',
'ftp/ftp_directory_listing_parser.cc',
'ftp/ftp_directory_listing_parser.h',
- 'ftp/ftp_directory_listing_parser_hprc.cc',
- 'ftp/ftp_directory_listing_parser_hprc.h',
'ftp/ftp_directory_listing_parser_ls.cc',
'ftp/ftp_directory_listing_parser_ls.h',
- 'ftp/ftp_directory_listing_parser_mlsd.cc',
- 'ftp/ftp_directory_listing_parser_mlsd.h',
'ftp/ftp_directory_listing_parser_netware.cc',
'ftp/ftp_directory_listing_parser_netware.h',
'ftp/ftp_directory_listing_parser_vms.cc',
@@ -519,6 +527,7 @@
'http/md4.h',
'http/partial_data.cc',
'http/partial_data.h',
+ 'http/proxy_client_socket.h',
'http/stream_factory.h',
'ocsp/nss_ocsp.cc',
'ocsp/nss_ocsp.h',
@@ -533,6 +542,7 @@
'proxy/proxy_config.cc',
'proxy/proxy_config.h',
'proxy/proxy_config_service.h',
+ 'proxy/proxy_config_service_fixed.cc',
'proxy/proxy_config_service_fixed.h',
'proxy/proxy_config_service_linux.cc',
'proxy/proxy_config_service_linux.h',
@@ -584,6 +594,8 @@
'socket/client_socket_pool_manager.h',
'socket/dns_cert_provenance_checker.cc',
'socket/dns_cert_provenance_checker.h',
+ 'socket/nss_ssl_util.cc',
+ 'socket/nss_ssl_util.h',
'socket/socket.h',
'socket/socks5_client_socket.cc',
'socket/socks5_client_socket.h',
@@ -591,6 +603,7 @@
'socket/socks_client_socket.h',
'socket/socks_client_socket_pool.cc',
'socket/socks_client_socket_pool.h',
+ 'socket/ssl_client_socket.cc',
'socket/ssl_client_socket.h',
'socket/ssl_client_socket_mac.cc',
'socket/ssl_client_socket_mac.h',
@@ -608,6 +621,11 @@
'socket/ssl_client_socket_win.h',
'socket/ssl_error_params.cc',
'socket/ssl_error_params.h',
+ 'socket/ssl_server_socket.h',
+ 'socket/ssl_server_socket_nss.cc',
+ 'socket/ssl_server_socket_nss.h',
+ 'socket/ssl_host_info.cc',
+ 'socket/ssl_host_info.h',
'socket/tcp_client_socket.cc',
'socket/tcp_client_socket.h',
'socket/tcp_client_socket_libevent.cc',
@@ -707,6 +725,7 @@
'websockets/websocket_handshake_handler.h',
'websockets/websocket_job.cc',
'websockets/websocket_job.h',
+ 'websockets/websocket_net_log_params.cc',
'websockets/websocket_net_log_params.h',
'websockets/websocket_throttle.cc',
'websockets/websocket_throttle.h',
@@ -732,10 +751,14 @@
'ocsp/nss_ocsp.h',
'socket/dns_cert_provenance_check.cc',
'socket/dns_cert_provenance_check.h',
+ 'socket/nss_ssl_util.cc',
+ 'socket/nss_ssl_util.h',
'socket/ssl_client_socket_nss.cc',
'socket/ssl_client_socket_nss.h',
'socket/ssl_client_socket_nss_factory.cc',
'socket/ssl_client_socket_nss_factory.h',
+ 'socket/ssl_server_socket_nss.cc',
+ 'socket/ssl_server_socket_nss.h',
],
},
{ # else !use_openssl: remove the unneeded files
@@ -753,7 +776,7 @@
'conditions': [
['use_openssl==1', {
'dependencies': [
- '../build/linux/system.gyp:openssl',
+ '../third_party/openssl/openssl.gyp:openssl',
],
},
{ # else use_openssl==0, use NSS
@@ -829,6 +852,7 @@
'sources': [
'base/address_list_unittest.cc',
'base/cert_database_nss_unittest.cc',
+ 'base/cert_verifier_unittest.cc',
'base/cookie_monster_unittest.cc',
'base/data_url_unittest.cc',
'base/directory_lister_unittest.cc',
@@ -839,7 +863,6 @@
'base/file_stream_unittest.cc',
'base/filter_unittest.cc',
'base/filter_unittest.h',
- 'base/forwarding_net_log_unittest.cc',
'base/gzip_filter_unittest.cc',
'base/host_cache_unittest.cc',
'base/host_mapping_rules_unittest.cc',
@@ -851,6 +874,7 @@
'base/mapped_host_resolver_unittest.cc',
'base/mime_sniffer_unittest.cc',
'base/mime_util_unittest.cc',
+ 'base/net_log_unittest.cc',
'base/net_log_unittest.h',
'base/net_test_suite.h',
'base/net_util_unittest.cc',
@@ -886,8 +910,6 @@
'ftp/ftp_ctrl_response_buffer_unittest.cc',
'ftp/ftp_directory_listing_buffer_unittest.cc',
'ftp/ftp_directory_listing_parser_ls_unittest.cc',
- 'ftp/ftp_directory_listing_parser_hprc_unittest.cc',
- 'ftp/ftp_directory_listing_parser_mlsd_unittest.cc',
'ftp/ftp_directory_listing_parser_netware_unittest.cc',
'ftp/ftp_directory_listing_parser_vms_unittest.cc',
'ftp/ftp_directory_listing_parser_windows_unittest.cc',
@@ -947,6 +969,7 @@
'socket/socks_client_socket_unittest.cc',
'socket/ssl_client_socket_unittest.cc',
'socket/ssl_client_socket_pool_unittest.cc',
+ 'socket/ssl_server_socket_unittest.cc',
'socket/tcp_client_socket_pool_unittest.cc',
'socket/tcp_client_socket_unittest.cc',
'socket_stream/socket_stream_metrics_unittest.cc',
@@ -1040,46 +1063,6 @@
],
},
{
- # This is a separate target in order to limit the scope of the protobuf
- # includes.
- 'target_name': 'ssl_host_info',
- 'type': '<(library)',
- 'dependencies': [
- '../base/base.gyp:base',
- '../third_party/protobuf/protobuf.gyp:protobuf_lite',
- '../third_party/protobuf/protobuf.gyp:protoc#host',
- ],
- 'sources': [
- 'socket/ssl_host_info.proto',
- 'socket/ssl_host_info.cc',
- 'socket/ssl_host_info.h',
- ],
- 'rules': [
- {
- 'rule_name': 'genproto',
- 'extension': 'proto',
- 'inputs': [
- '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
- ],
- 'outputs': [
- '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net/socket/<(RULE_INPUT_ROOT).pb.h',
- '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net/socket/<(RULE_INPUT_ROOT).pb.cc',
- ],
- 'action': [
- '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
- 'socket/<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)',
- '--cpp_out=<(SHARED_INTERMEDIATE_DIR)/protoc_out/net',
- ],
- 'message': 'Generating C++ code from <(RULE_INPUT_PATH)',
- 'process_outputs_as_sources': 1,
- },
- ],
- 'include_dirs': [
- '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net',
- '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
- ],
- },
- {
'target_name': 'net_perftests',
'type': 'executable',
'dependencies': [
@@ -1196,8 +1179,8 @@
'conditions': [
['use_openssl==1', {
'dependencies': [
- '../build/linux/system.gyp:openssl',
- ]
+ '../third_party/openssl/openssl.gyp:openssl',
+ ],
}, {
'dependencies': [
'../build/linux/system.gyp:nss',
diff --git a/net/ocsp/nss_ocsp.cc b/net/ocsp/nss_ocsp.cc
index 7618f9e..02edd05 100644
--- a/net/ocsp/nss_ocsp.cc
+++ b/net/ocsp/nss_ocsp.cc
@@ -140,13 +140,13 @@ base::LazyInstance<OCSPNSSInitialization> g_ocsp_nss_initialization(
base::LINKER_INITIALIZED);
// Concrete class for SEC_HTTP_REQUEST_SESSION.
-// Public methods except virtual methods of URLRequest::Delegate (On* methods)
-// run on certificate verifier thread (worker thread).
-// Virtual methods of URLRequest::Delegate and private methods run
+// Public methods except virtual methods of net::URLRequest::Delegate
+// (On* methods) run on certificate verifier thread (worker thread).
+// Virtual methods of net::URLRequest::Delegate and private methods run
// on IO thread.
class OCSPRequestSession
: public base::RefCountedThreadSafe<OCSPRequestSession>,
- public URLRequest::Delegate {
+ public net::URLRequest::Delegate {
public:
OCSPRequestSession(const GURL& url,
const char* http_request_method,
@@ -248,7 +248,20 @@ class OCSPRequestSession
return data_;
}
- virtual void OnResponseStarted(URLRequest* request) {
+ virtual void OnReceivedRedirect(net::URLRequest* request,
+ const GURL& new_url,
+ bool* defer_redirect) {
+ DCHECK_EQ(request, request_);
+ DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
+
+ if (!new_url.SchemeIs("http")) {
+ // Prevent redirects to non-HTTP schemes, including HTTPS. This matches
+ // the initial check in OCSPServerSession::CreateRequest().
+ CancelURLRequest();
+ }
+ }
+
+ virtual void OnResponseStarted(net::URLRequest* request) {
DCHECK_EQ(request, request_);
DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
@@ -262,7 +275,7 @@ class OCSPRequestSession
OnReadCompleted(request_, bytes_read);
}
- virtual void OnReadCompleted(URLRequest* request, int bytes_read) {
+ virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) {
DCHECK_EQ(request, request_);
DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
@@ -349,7 +362,7 @@ class OCSPRequestSession
g_ocsp_io_loop.Get().AddRequest(this);
}
- request_ = new URLRequest(url_, this);
+ request_ = new net::URLRequest(url_, this);
request_->set_context(url_request_context);
// To meet the privacy requirements of off-the-record mode.
request_->set_load_flags(
@@ -376,7 +389,7 @@ class OCSPRequestSession
GURL url_; // The URL we eventually wound up at
std::string http_request_method_;
base::TimeDelta timeout_; // The timeout for OCSP
- URLRequest* request_; // The actual request this wraps
+ net::URLRequest* request_; // The actual request this wraps
scoped_refptr<net::IOBuffer> buffer_; // Read buffer
net::HttpRequestHeaders extra_request_headers_;
std::string upload_content_; // HTTP POST payload
@@ -567,7 +580,7 @@ SECStatus OCSPCreateSession(const char* host, PRUint16 portnum,
if (request_context == NULL) {
LOG(ERROR) << "No URLRequestContext for OCSP handler.";
// The application failed to call SetURLRequestContextForOCSP, so we
- // can't create and use URLRequest. PR_NOT_IMPLEMENTED_ERROR is not an
+ // can't create and use net::URLRequest. PR_NOT_IMPLEMENTED_ERROR is not an
// accurate error code for this error condition, but is close enough.
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
return SECFailure;
diff --git a/net/proxy/init_proxy_resolver_unittest.cc b/net/proxy/init_proxy_resolver_unittest.cc
index 0c7e8a1..c1a69d1 100644
--- a/net/proxy/init_proxy_resolver_unittest.cc
+++ b/net/proxy/init_proxy_resolver_unittest.cc
@@ -107,6 +107,8 @@ class RuleBasedProxyScriptFetcher : public ProxyScriptFetcher {
virtual void Cancel() {}
+ virtual URLRequestContext* GetRequestContext() { return NULL; }
+
private:
const Rules* rules_;
};
@@ -130,6 +132,10 @@ class RuleBasedProxyResolver : public ProxyResolver {
NOTREACHED();
}
+ virtual void CancelSetPacScript() {
+ NOTREACHED();
+ }
+
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& script_data,
CompletionCallback* callback) {
@@ -181,19 +187,22 @@ TEST(InitProxyResolverTest, CustomPacSucceeds) {
EXPECT_EQ(rule.text(), resolver.script_data()->utf16());
// Check the NetLog was filled correctly.
- EXPECT_EQ(6u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(6u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 3, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
+ entries, 3, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 4, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
+ entries, 4, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 5, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 5, NetLog::TYPE_INIT_PROXY_RESOLVER));
}
// Fail downloading the custom PAC script.
@@ -215,15 +224,18 @@ TEST(InitProxyResolverTest, CustomPacFails1) {
EXPECT_EQ(NULL, resolver.script_data());
// Check the NetLog was filled correctly.
- EXPECT_EQ(4u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(4u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 3, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 3, NetLog::TYPE_INIT_PROXY_RESOLVER));
}
// Fail parsing the custom PAC script.
@@ -326,31 +338,34 @@ TEST(InitProxyResolverTest, AutodetectFailCustomSuccess2) {
// Check the NetLog was filled correctly.
// (Note that the Fetch and Set states are repeated since both WPAD and custom
// PAC scripts are tried).
- EXPECT_EQ(11u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(11u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 3, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
+ entries, 3, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 4, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
+ entries, 4, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 5,
+ entries, 5,
NetLog::TYPE_INIT_PROXY_RESOLVER_FALLING_BACK_TO_NEXT_PAC_URL,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 6, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 6, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 7, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 7, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 8, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
+ entries, 8, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 9, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
+ entries, 9, NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 10, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 10, NetLog::TYPE_INIT_PROXY_RESOLVER));
}
// Fails at WPAD (downloading), and fails at custom PAC (downloading).
@@ -438,19 +453,22 @@ TEST(InitProxyResolverTest, CustomPacFails1_WithPositiveDelay) {
EXPECT_EQ(NULL, resolver.script_data());
// Check the NetLog was filled correctly.
- EXPECT_EQ(6u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(6u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 1, NetLog::TYPE_INIT_PROXY_RESOLVER_WAIT));
+ entries, 1, NetLog::TYPE_INIT_PROXY_RESOLVER_WAIT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_INIT_PROXY_RESOLVER_WAIT));
+ entries, 2, NetLog::TYPE_INIT_PROXY_RESOLVER_WAIT));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 3, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 3, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 4, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 4, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 5, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 5, NetLog::TYPE_INIT_PROXY_RESOLVER));
}
// This is a copy-paste of CustomPacFails1, with the exception that we give it
@@ -475,15 +493,18 @@ TEST(InitProxyResolverTest, CustomPacFails1_WithNegativeDelay) {
EXPECT_EQ(NULL, resolver.script_data());
// Check the NetLog was filled correctly.
- EXPECT_EQ(4u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(4u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 0, NetLog::TYPE_INIT_PROXY_RESOLVER));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 1, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
+ entries, 2, NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 3, NetLog::TYPE_INIT_PROXY_RESOLVER));
+ entries, 3, NetLog::TYPE_INIT_PROXY_RESOLVER));
}
} // namespace
diff --git a/net/proxy/multi_threaded_proxy_resolver.cc b/net/proxy/multi_threaded_proxy_resolver.cc
index d696438..6c348d2 100644
--- a/net/proxy/multi_threaded_proxy_resolver.cc
+++ b/net/proxy/multi_threaded_proxy_resolver.cc
@@ -8,8 +8,8 @@
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/thread.h"
-#include "net/base/capturing_net_log.h"
#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
#include "net/proxy/proxy_info.h"
// TODO(eroman): Have the MultiThreadedProxyResolver clear its PAC script
@@ -253,13 +253,9 @@ class MultiThreadedProxyResolver::GetProxyForURLJob
// Runs on the worker thread.
virtual void Run(MessageLoop* origin_loop) {
- const size_t kNetLogBound = 50u;
- worker_log_.reset(new CapturingNetLog(kNetLogBound));
- BoundNetLog bound_worker_log(NetLog::Source(), worker_log_.get());
-
ProxyResolver* resolver = executor()->resolver();
int rv = resolver->GetProxyForURL(
- url_, &results_buf_, NULL, NULL, bound_worker_log);
+ url_, &results_buf_, NULL, NULL, net_log_);
DCHECK_NE(rv, ERR_IO_PENDING);
origin_loop->PostTask(
@@ -272,12 +268,6 @@ class MultiThreadedProxyResolver::GetProxyForURLJob
void QueryComplete(int result_code) {
// The Job may have been cancelled after it was started.
if (!was_cancelled()) {
- // Merge the load log that was generated on the worker thread, into the
- // main log.
- CapturingBoundNetLog bound_worker_log(NetLog::Source(),
- worker_log_.release());
- bound_worker_log.AppendTo(net_log_);
-
if (result_code >= OK) { // Note: unit-tests use values > 0.
results_->Use(results_buf_);
}
@@ -288,16 +278,14 @@ class MultiThreadedProxyResolver::GetProxyForURLJob
// Must only be used on the "origin" thread.
ProxyInfo* results_;
+
+ // Can be used on either "origin" or worker thread.
BoundNetLog net_log_;
const GURL url_;
// Usable from within DoQuery on the worker thread.
ProxyInfo results_buf_;
- // Used to pass the captured events between DoQuery [worker thread] and
- // QueryComplete [origin thread].
- scoped_ptr<CapturingNetLog> worker_log_;
-
bool was_waiting_for_thread_;
};
@@ -318,7 +306,7 @@ MultiThreadedProxyResolver::Executor::Executor(
std::string thread_name =
base::StringPrintf("PAC thread #%d", thread_number);
thread_.reset(new base::Thread(thread_name.c_str()));
- thread_->Start();
+ CHECK(thread_->Start());
}
void MultiThreadedProxyResolver::Executor::StartJob(Job* job) {
diff --git a/net/proxy/multi_threaded_proxy_resolver_unittest.cc b/net/proxy/multi_threaded_proxy_resolver_unittest.cc
index 7027161..a18804f 100644
--- a/net/proxy/multi_threaded_proxy_resolver_unittest.cc
+++ b/net/proxy/multi_threaded_proxy_resolver_unittest.cc
@@ -60,6 +60,10 @@ class MockProxyResolver : public ProxyResolver {
NOTREACHED();
}
+ virtual void CancelSetPacScript() {
+ NOTREACHED();
+ }
+
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& script_data,
CompletionCallback* callback) {
@@ -169,6 +173,10 @@ class ForwardingProxyResolver : public ProxyResolver {
impl_->CancelRequest(request);
}
+ virtual void CancelSetPacScript() {
+ impl_->CancelSetPacScript();
+ }
+
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& script_data,
CompletionCallback* callback) {
@@ -260,9 +268,11 @@ TEST(MultiThreadedProxyResolverTest, SingleThread_Basic) {
// on completion, this should have been copied into |log0|.
// We also have 1 log entry that was emitted by the
// MultiThreadedProxyResolver.
- ASSERT_EQ(2u, log0.entries().size());
- EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD,
- log0.entries()[0].type);
+ net::CapturingNetLog::EntryList entries0;
+ log0.GetEntries(&entries0);
+
+ ASSERT_EQ(2u, entries0.size());
+ EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, entries0[0].type);
// Start 3 more requests (request1 to request3).
@@ -368,30 +378,42 @@ TEST(MultiThreadedProxyResolverTest,
// 1 entry from the mock proxy resolver.
EXPECT_EQ(0, callback0.WaitForResult());
EXPECT_EQ("PROXY request0:80", results0.ToPacString());
- ASSERT_EQ(2u, log0.entries().size());
+
+ net::CapturingNetLog::EntryList entries0;
+ log0.GetEntries(&entries0);
+
+ ASSERT_EQ(2u, entries0.size());
EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD,
- log0.entries()[0].type);
+ entries0[0].type);
// Check that request 1 completed as expected.
EXPECT_EQ(1, callback1.WaitForResult());
EXPECT_EQ("PROXY request1:80", results1.ToPacString());
- ASSERT_EQ(4u, log1.entries().size());
+
+ net::CapturingNetLog::EntryList entries1;
+ log1.GetEntries(&entries1);
+
+ ASSERT_EQ(4u, entries1.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log1.entries(), 0,
+ entries1, 0,
NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
EXPECT_TRUE(LogContainsEndEvent(
- log1.entries(), 1,
+ entries1, 1,
NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
// Check that request 2 completed as expected.
EXPECT_EQ(2, callback2.WaitForResult());
EXPECT_EQ("PROXY request2:80", results2.ToPacString());
- ASSERT_EQ(4u, log2.entries().size());
+
+ net::CapturingNetLog::EntryList entries2;
+ log2.GetEntries(&entries2);
+
+ ASSERT_EQ(4u, entries2.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log2.entries(), 0,
+ entries2, 0,
NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
EXPECT_TRUE(LogContainsEndEvent(
- log2.entries(), 1,
+ entries2, 1,
NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD));
}
diff --git a/net/proxy/proxy_bypass_rules.cc b/net/proxy/proxy_bypass_rules.cc
index ce018bf..91c6f44 100644
--- a/net/proxy/proxy_bypass_rules.cc
+++ b/net/proxy/proxy_bypass_rules.cc
@@ -4,6 +4,7 @@
#include "net/proxy/proxy_bypass_rules.h"
+#include "base/stl_util-inl.h"
#include "base/string_number_conversions.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"
@@ -45,6 +46,12 @@ class HostnamePatternRule : public ProxyBypassRules::Rule {
return str;
}
+ virtual Rule* Clone() const {
+ return new HostnamePatternRule(optional_scheme_,
+ hostname_pattern_,
+ optional_port_);
+ }
+
private:
const std::string optional_scheme_;
const std::string hostname_pattern_;
@@ -63,6 +70,10 @@ class BypassLocalRule : public ProxyBypassRules::Rule {
virtual std::string ToString() const {
return "<local>";
}
+
+ virtual Rule* Clone() const {
+ return new BypassLocalRule();
+ }
};
// Rule for matching a URL that is an IP address, if that IP address falls
@@ -102,6 +113,13 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule {
return description_;
}
+ virtual Rule* Clone() const {
+ return new BypassIPBlockRule(description_,
+ optional_scheme_,
+ ip_prefix_,
+ prefix_length_in_bits_);
+ }
+
private:
const std::string description_;
const std::string optional_scheme_;
@@ -122,18 +140,29 @@ bool IsIPAddress(const std::string& domain) {
} // namespace
+ProxyBypassRules::Rule::Rule() {
+}
+
+ProxyBypassRules::Rule::~Rule() {
+}
+
+bool ProxyBypassRules::Rule::Equals(const Rule& rule) const {
+ return ToString() == rule.ToString();
+}
+
ProxyBypassRules::ProxyBypassRules() {
}
-ProxyBypassRules::ProxyBypassRules(const ProxyBypassRules& rhs)
- : rules_(rhs.rules_) {
+ProxyBypassRules::ProxyBypassRules(const ProxyBypassRules& rhs) {
+ AssignFrom(rhs);
}
ProxyBypassRules::~ProxyBypassRules() {
+ Clear();
}
ProxyBypassRules& ProxyBypassRules::operator=(const ProxyBypassRules& rhs) {
- rules_ = rhs.rules_;
+ AssignFrom(rhs);
return *this;
}
@@ -146,11 +175,11 @@ bool ProxyBypassRules::Matches(const GURL& url) const {
}
bool ProxyBypassRules::Equals(const ProxyBypassRules& other) const {
- if (rules_.size() != other.rules().size())
+ if (rules_.size() != other.rules_.size())
return false;
for (size_t i = 0; i < rules_.size(); ++i) {
- if (!rules_[i]->Equals(*other.rules()[i]))
+ if (!rules_[i]->Equals(*other.rules_[i]))
return false;
}
return true;
@@ -171,14 +200,14 @@ bool ProxyBypassRules::AddRuleForHostname(const std::string& optional_scheme,
if (hostname_pattern.empty())
return false;
- rules_.push_back(make_scoped_refptr(new HostnamePatternRule(optional_scheme,
- hostname_pattern,
- optional_port)));
+ rules_.push_back(new HostnamePatternRule(optional_scheme,
+ hostname_pattern,
+ optional_port));
return true;
}
void ProxyBypassRules::AddRuleToBypassLocal() {
- rules_.push_back(make_scoped_refptr(new BypassLocalRule));
+ rules_.push_back(new BypassLocalRule);
}
bool ProxyBypassRules::AddRuleFromString(const std::string& raw) {
@@ -191,7 +220,17 @@ bool ProxyBypassRules::AddRuleFromStringUsingSuffixMatching(
}
void ProxyBypassRules::Clear() {
- rules_.clear();
+ STLDeleteElements(&rules_);
+}
+
+void ProxyBypassRules::AssignFrom(const ProxyBypassRules& other) {
+ Clear();
+
+ // Make a copy of the rules list.
+ for (RuleList::const_iterator it = other.rules_.begin();
+ it != other.rules_.end(); ++it) {
+ rules_.push_back((*it)->Clone());
+ }
}
void ProxyBypassRules::ParseFromStringInternal(
@@ -241,8 +280,8 @@ bool ProxyBypassRules::AddRuleFromStringInternal(
if (!ParseCIDRBlock(raw, &ip_prefix, &prefix_length_in_bits))
return false;
- rules_.push_back(make_scoped_refptr(
- new BypassIPBlockRule(raw, scheme, ip_prefix, prefix_length_in_bits)));
+ rules_.push_back(
+ new BypassIPBlockRule(raw, scheme, ip_prefix, prefix_length_in_bits));
return true;
}
diff --git a/net/proxy/proxy_bypass_rules.h b/net/proxy/proxy_bypass_rules.h
index 9873154..ad8afdc 100644
--- a/net/proxy/proxy_bypass_rules.h
+++ b/net/proxy/proxy_bypass_rules.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/ref_counted.h"
#include "googleurl/src/gurl.h"
namespace net {
@@ -20,10 +19,10 @@ namespace net {
class ProxyBypassRules {
public:
// Interface for an individual proxy bypass rule.
- class Rule : public base::RefCounted<Rule> {
+ class Rule {
public:
- Rule() {}
- virtual ~Rule() {}
+ Rule();
+ virtual ~Rule();
// Returns true if |url| matches the rule.
virtual bool Matches(const GURL& url) const = 0;
@@ -32,15 +31,16 @@ class ProxyBypassRules {
// visualizing the rules, and also to test equality of a rules list.
virtual std::string ToString() const = 0;
- bool Equals(const Rule& rule) const {
- return ToString() == rule.ToString();
- }
+ // Creates a copy of this rule. (Caller is responsible for deleting it)
+ virtual Rule* Clone() const = 0;
+
+ bool Equals(const Rule& rule) const;
private:
DISALLOW_COPY_AND_ASSIGN(Rule);
};
- typedef std::vector<scoped_refptr<Rule> > RuleList;
+ typedef std::vector<const Rule*> RuleList;
// Note: This class supports copy constructor and assignment.
ProxyBypassRules();
@@ -48,7 +48,9 @@ class ProxyBypassRules {
~ProxyBypassRules();
ProxyBypassRules& operator=(const ProxyBypassRules& rhs);
- // Returns the current list of rules.
+ // Returns the current list of rules. The rules list contains pointers
+ // which are owned by this class, callers should NOT keep references
+ // or delete them.
const RuleList& rules() const { return rules_; }
// Returns true if |url| matches any of the proxy bypass rules.
@@ -154,6 +156,9 @@ class ProxyBypassRules {
// Removes all the rules.
void Clear();
+ // Sets |*this| to |other|.
+ void AssignFrom(const ProxyBypassRules& other);
+
private:
// The following are variants of ParseFromString() and AddRuleFromString(),
// which additionally prefix hostname patterns with a wildcard if
diff --git a/net/proxy/proxy_config_service_fixed.cc b/net/proxy/proxy_config_service_fixed.cc
new file mode 100644
index 0000000..b23c265
--- /dev/null
+++ b/net/proxy/proxy_config_service_fixed.cc
@@ -0,0 +1,20 @@
+// 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/proxy/proxy_config_service_fixed.h"
+
+namespace net {
+
+ProxyConfigServiceFixed::ProxyConfigServiceFixed(const ProxyConfig& pc)
+ : pc_(pc) {
+}
+
+ProxyConfigServiceFixed::~ProxyConfigServiceFixed() {}
+
+bool ProxyConfigServiceFixed::GetLatestProxyConfig(ProxyConfig* config) {
+ *config = pc_;
+ return true;
+}
+
+} // namespace net
diff --git a/net/proxy/proxy_config_service_fixed.h b/net/proxy/proxy_config_service_fixed.h
index e9eac8e..b0d8f03 100644
--- a/net/proxy/proxy_config_service_fixed.h
+++ b/net/proxy/proxy_config_service_fixed.h
@@ -15,15 +15,13 @@ namespace net {
// Implementation of ProxyConfigService that returns a fixed result.
class ProxyConfigServiceFixed : public ProxyConfigService {
public:
- explicit ProxyConfigServiceFixed(const ProxyConfig& pc) : pc_(pc) {}
+ explicit ProxyConfigServiceFixed(const ProxyConfig& pc);
+ virtual ~ProxyConfigServiceFixed();
// ProxyConfigService methods:
virtual void AddObserver(Observer* observer) {}
virtual void RemoveObserver(Observer* observer) {}
- virtual bool GetLatestProxyConfig(ProxyConfig* config) {
- *config = pc_;
- return true;
- }
+ virtual bool GetLatestProxyConfig(ProxyConfig* config);
private:
ProxyConfig pc_;
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc
index 5e548cf..3867df1 100644
--- a/net/proxy/proxy_config_service_linux.cc
+++ b/net/proxy/proxy_config_service_linux.cc
@@ -1255,4 +1255,16 @@ ProxyConfigServiceLinux::ProxyConfigServiceLinux(
: delegate_(new Delegate(env_var_getter, gconf_getter)) {
}
+void ProxyConfigServiceLinux::AddObserver(Observer* observer) {
+ delegate_->AddObserver(observer);
+}
+
+void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) {
+ delegate_->RemoveObserver(observer);
+}
+
+bool ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) {
+ return delegate_->GetLatestProxyConfig(config);
+}
+
} // namespace net
diff --git a/net/proxy/proxy_config_service_linux.h b/net/proxy/proxy_config_service_linux.h
index db2492c..ca82822 100644
--- a/net/proxy/proxy_config_service_linux.h
+++ b/net/proxy/proxy_config_service_linux.h
@@ -239,18 +239,9 @@ class ProxyConfigServiceLinux : public ProxyConfigService {
// ProxyConfigService methods:
// Called from IO thread.
-
- virtual void AddObserver(Observer* observer) {
- delegate_->AddObserver(observer);
- }
-
- virtual void RemoveObserver(Observer* observer) {
- delegate_->RemoveObserver(observer);
- }
-
- virtual bool GetLatestProxyConfig(ProxyConfig* config) {
- return delegate_->GetLatestProxyConfig(config);
- }
+ virtual void AddObserver(Observer* observer);
+ virtual void RemoveObserver(Observer* observer);
+ virtual bool GetLatestProxyConfig(ProxyConfig* config);
private:
scoped_refptr<Delegate> delegate_;
diff --git a/net/proxy/proxy_resolver.h b/net/proxy/proxy_resolver.h
index 9220f5e..fcc2395 100644
--- a/net/proxy/proxy_resolver.h
+++ b/net/proxy/proxy_resolver.h
@@ -54,10 +54,7 @@ class ProxyResolver {
// contain the actual script bytes rather than just the URL.
bool expects_pac_bytes() const { return expects_pac_bytes_; }
- // TODO(eroman): Make this =0.
- virtual void CancelSetPacScript() {
- NOTREACHED();
- }
+ virtual void CancelSetPacScript() = 0;
// Frees any unneeded memory held by the resolver, e.g. garbage in the JS
// engine. Most subclasses don't need to do anything, so we provide a default
diff --git a/net/proxy/proxy_resolver_js_bindings_unittest.cc b/net/proxy/proxy_resolver_js_bindings_unittest.cc
index 6b33a34..ecb36ca 100644
--- a/net/proxy/proxy_resolver_js_bindings_unittest.cc
+++ b/net/proxy/proxy_resolver_js_bindings_unittest.cc
@@ -304,65 +304,82 @@ TEST(ProxyResolverJSBindingsTest, NetLog) {
bindings->set_current_request_context(&context);
std::string ip_address;
-
- ASSERT_EQ(0u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+ ASSERT_EQ(0u, entries.size());
// Call all the bindings. Each call should be logging something to
// our NetLog.
bindings->MyIpAddress(&ip_address);
- EXPECT_EQ(2u, log.entries().size());
+
+ log.GetEntries(&entries);
+ EXPECT_EQ(2u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS));
+ entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 1, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS));
+ entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS));
bindings->MyIpAddressEx(&ip_address);
- EXPECT_EQ(4u, log.entries().size());
+
+ log.GetEntries(&entries);
+ EXPECT_EQ(4u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 2, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX));
+ entries, 2, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 3, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX));
+ entries, 3, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX));
bindings->DnsResolve("foo", &ip_address);
- EXPECT_EQ(6u, log.entries().size());
+
+ log.GetEntries(&entries);
+ EXPECT_EQ(6u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 4, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE));
+ entries, 4, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 5, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE));
+ entries, 5, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE));
bindings->DnsResolveEx("foo", &ip_address);
- EXPECT_EQ(8u, log.entries().size());
+
+ log.GetEntries(&entries);
+ EXPECT_EQ(8u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 6, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX));
+ entries, 6, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 7, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX));
+ entries, 7, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX));
// Nothing has been emitted globally yet.
- EXPECT_EQ(0u, global_log.entries().size());
+ net::CapturingNetLog::EntryList global_log_entries;
+ global_log.GetEntries(&global_log_entries);
+ EXPECT_EQ(0u, global_log_entries.size());
bindings->OnError(30, string16());
- EXPECT_EQ(9u, log.entries().size());
+
+ log.GetEntries(&entries);
+ EXPECT_EQ(9u, entries.size());
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 8, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
+ entries, 8, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
NetLog::PHASE_NONE));
// We also emit errors to the top-level log stream.
- EXPECT_EQ(1u, global_log.entries().size());
+ global_log.GetEntries(&global_log_entries);
+ EXPECT_EQ(1u, global_log_entries.size());
EXPECT_TRUE(LogContainsEvent(
- global_log.entries(), 0, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
+ global_log_entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
NetLog::PHASE_NONE));
bindings->Alert(string16());
- EXPECT_EQ(10u, log.entries().size());
+
+ log.GetEntries(&entries);
+ EXPECT_EQ(10u, entries.size());
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 9, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
+ entries, 9, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
NetLog::PHASE_NONE));
// We also emit javascript alerts to the top-level log stream.
- EXPECT_EQ(2u, global_log.entries().size());
+ global_log.GetEntries(&global_log_entries);
+ EXPECT_EQ(2u, global_log_entries.size());
EXPECT_TRUE(LogContainsEvent(
- global_log.entries(), 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
+ global_log_entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
NetLog::PHASE_NONE));
}
diff --git a/net/proxy/proxy_resolver_mac.cc b/net/proxy/proxy_resolver_mac.cc
index 442715d..128450f 100644
--- a/net/proxy/proxy_resolver_mac.cc
+++ b/net/proxy/proxy_resolver_mac.cc
@@ -53,6 +53,12 @@ void ResultCallback(void* client, CFArrayRef proxies, CFErrorRef error) {
namespace net {
+ProxyResolverMac::ProxyResolverMac()
+ : ProxyResolver(false /*expects_pac_bytes*/) {
+}
+
+ProxyResolverMac::~ProxyResolverMac() {}
+
// Gets the proxy information for a query URL from a PAC. Implementation
// inspired by http://developer.apple.com/samplecode/CFProxySupportTool/
int ProxyResolverMac::GetProxyForURL(const GURL& query_url,
@@ -171,4 +177,19 @@ int ProxyResolverMac::GetProxyForURL(const GURL& query_url,
return OK;
}
+void ProxyResolverMac::CancelRequest(RequestHandle request) {
+ NOTREACHED();
+}
+
+void ProxyResolverMac::CancelSetPacScript() {
+ NOTREACHED();
+}
+
+int ProxyResolverMac::SetPacScript(
+ const scoped_refptr<ProxyResolverScriptData>& script_data,
+ CompletionCallback* /*callback*/) {
+ script_data_ = script_data;
+ return OK;
+}
+
} // namespace net
diff --git a/net/proxy/proxy_resolver_mac.h b/net/proxy/proxy_resolver_mac.h
index 950b11f..fe6e791 100644
--- a/net/proxy/proxy_resolver_mac.h
+++ b/net/proxy/proxy_resolver_mac.h
@@ -16,7 +16,8 @@ namespace net {
// proxies.
class ProxyResolverMac : public ProxyResolver {
public:
- ProxyResolverMac() : ProxyResolver(false /*expects_pac_bytes*/) {}
+ ProxyResolverMac();
+ virtual ~ProxyResolverMac();
// ProxyResolver methods:
virtual int GetProxyForURL(const GURL& url,
@@ -25,16 +26,13 @@ class ProxyResolverMac : public ProxyResolver {
RequestHandle* request,
const BoundNetLog& net_log);
- virtual void CancelRequest(RequestHandle request) {
- NOTREACHED();
- }
+ virtual void CancelRequest(RequestHandle request);
+
+ virtual void CancelSetPacScript();
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& script_data,
- CompletionCallback* /*callback*/) {
- script_data_ = script_data;
- return OK;
- }
+ CompletionCallback* /*callback*/);
private:
scoped_refptr<ProxyResolverScriptData> script_data_;
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc
index 2bf3b6d..80a1937 100644
--- a/net/proxy/proxy_resolver_v8.cc
+++ b/net/proxy/proxy_resolver_v8.cc
@@ -721,6 +721,10 @@ void ProxyResolverV8::CancelRequest(RequestHandle request) {
NOTREACHED();
}
+void ProxyResolverV8::CancelSetPacScript() {
+ NOTREACHED();
+}
+
void ProxyResolverV8::PurgeMemory() {
context_->PurgeMemory();
}
diff --git a/net/proxy/proxy_resolver_v8.h b/net/proxy/proxy_resolver_v8.h
index 7345f45..28bdcd0 100644
--- a/net/proxy/proxy_resolver_v8.h
+++ b/net/proxy/proxy_resolver_v8.h
@@ -47,6 +47,7 @@ class ProxyResolverV8 : public ProxyResolver {
RequestHandle* /*request*/,
const BoundNetLog& net_log);
virtual void CancelRequest(RequestHandle request);
+ virtual void CancelSetPacScript();
virtual void PurgeMemory();
virtual void Shutdown();
virtual int SetPacScript(
diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc
index 3e61cd7..eff0413 100644
--- a/net/proxy/proxy_resolver_v8_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_unittest.cc
@@ -138,8 +138,10 @@ TEST(ProxyResolverV8Test, Direct) {
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
// No bindings were called, so no log entries.
- EXPECT_EQ(0u, log.entries().size());
+ EXPECT_EQ(0u, entries.size());
}
TEST(ProxyResolverV8Test, ReturnEmptyString) {
diff --git a/net/proxy/proxy_resolver_winhttp.cc b/net/proxy/proxy_resolver_winhttp.cc
index 962271f..13f5fb5 100644
--- a/net/proxy/proxy_resolver_winhttp.cc
+++ b/net/proxy/proxy_resolver_winhttp.cc
@@ -21,23 +21,6 @@ using base::TimeTicks;
namespace net {
-// A small wrapper for histogramming purposes ;-)
-static BOOL CallWinHttpGetProxyForUrl(HINTERNET session, LPCWSTR url,
- WINHTTP_AUTOPROXY_OPTIONS* options,
- WINHTTP_PROXY_INFO* results) {
- TimeTicks time_start = TimeTicks::Now();
- BOOL rv = WinHttpGetProxyForUrl(session, url, options, results);
- TimeDelta time_delta = TimeTicks::Now() - time_start;
- // Record separately success and failure times since they will have very
- // different characteristics.
- if (rv) {
- UMA_HISTOGRAM_LONG_TIMES("Net.GetProxyForUrl_OK", time_delta);
- } else {
- UMA_HISTOGRAM_LONG_TIMES("Net.GetProxyForUrl_FAIL", time_delta);
- }
- return rv;
-}
-
static void FreeInfo(WINHTTP_PROXY_INFO* info) {
if (info->lpszProxy)
GlobalFree(info->lpszProxy);
@@ -82,12 +65,12 @@ int ProxyResolverWinHttp::GetProxyForURL(const GURL& query_url,
// Otherwise, we fail over to trying it with a value of true. This way we
// get good performance in the case where WinHTTP uses an out-of-process
// resolver. This is important for Vista and Win2k3.
- BOOL ok = CallWinHttpGetProxyForUrl(
+ BOOL ok = WinHttpGetProxyForUrl(
session_handle_, ASCIIToWide(query_url.spec()).c_str(), &options, &info);
if (!ok) {
if (ERROR_WINHTTP_LOGIN_FAILURE == GetLastError()) {
options.fAutoLogonIfChallenged = TRUE;
- ok = CallWinHttpGetProxyForUrl(
+ ok = WinHttpGetProxyForUrl(
session_handle_, ASCIIToWide(query_url.spec()).c_str(),
&options, &info);
}
@@ -141,6 +124,10 @@ void ProxyResolverWinHttp::CancelRequest(RequestHandle request) {
NOTREACHED();
}
+void ProxyResolverWinHttp::CancelSetPacScript() {
+ NOTREACHED();
+}
+
int ProxyResolverWinHttp::SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& script_data,
CompletionCallback* /*callback*/) {
diff --git a/net/proxy/proxy_resolver_winhttp.h b/net/proxy/proxy_resolver_winhttp.h
index 68d1109..9784672 100644
--- a/net/proxy/proxy_resolver_winhttp.h
+++ b/net/proxy/proxy_resolver_winhttp.h
@@ -27,6 +27,9 @@ class ProxyResolverWinHttp : public ProxyResolver {
RequestHandle* /*request*/,
const BoundNetLog& /*net_log*/);
virtual void CancelRequest(RequestHandle request);
+
+ virtual void CancelSetPacScript();
+
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& script_data,
CompletionCallback* /*callback*/);
diff --git a/net/proxy/proxy_script_fetcher.h b/net/proxy/proxy_script_fetcher.h
index 0a28065..bf33bcb 100644
--- a/net/proxy/proxy_script_fetcher.h
+++ b/net/proxy/proxy_script_fetcher.h
@@ -48,7 +48,7 @@ class ProxyScriptFetcher {
// Returns the request context that this fetcher uses to issue downloads,
// or NULL.
- virtual URLRequestContext* GetRequestContext() { return NULL; }
+ virtual URLRequestContext* GetRequestContext() = 0;
};
} // namespace net
diff --git a/net/proxy/proxy_script_fetcher_impl.cc b/net/proxy/proxy_script_fetcher_impl.cc
index 221e5c0..0a54046 100644
--- a/net/proxy/proxy_script_fetcher_impl.cc
+++ b/net/proxy/proxy_script_fetcher_impl.cc
@@ -86,7 +86,7 @@ ProxyScriptFetcherImpl::ProxyScriptFetcherImpl(
}
ProxyScriptFetcherImpl::~ProxyScriptFetcherImpl() {
- // The URLRequest's destructor will cancel the outstanding request, and
+ // The net::URLRequest's destructor will cancel the outstanding request, and
// ensure that the delegate (this) is not called again.
}
@@ -99,7 +99,7 @@ int ProxyScriptFetcherImpl::Fetch(const GURL& url,
DCHECK(callback);
DCHECK(text);
- cur_request_.reset(new URLRequest(url, this));
+ cur_request_.reset(new net::URLRequest(url, this));
cur_request_->set_context(url_request_context_);
cur_request_->set_method("GET");
@@ -129,7 +129,7 @@ int ProxyScriptFetcherImpl::Fetch(const GURL& url,
}
void ProxyScriptFetcherImpl::Cancel() {
- // ResetCurRequestState will free the URLRequest, which will cause
+ // ResetCurRequestState will free the net::URLRequest, which will cause
// cancellation.
ResetCurRequestState();
}
@@ -138,7 +138,7 @@ URLRequestContext* ProxyScriptFetcherImpl::GetRequestContext() {
return url_request_context_;
}
-void ProxyScriptFetcherImpl::OnAuthRequired(URLRequest* request,
+void ProxyScriptFetcherImpl::OnAuthRequired(net::URLRequest* request,
AuthChallengeInfo* auth_info) {
DCHECK_EQ(request, cur_request_.get());
// TODO(eroman):
@@ -147,7 +147,7 @@ void ProxyScriptFetcherImpl::OnAuthRequired(URLRequest* request,
request->CancelAuth();
}
-void ProxyScriptFetcherImpl::OnSSLCertificateError(URLRequest* request,
+void ProxyScriptFetcherImpl::OnSSLCertificateError(net::URLRequest* request,
int cert_error,
X509Certificate* cert) {
DCHECK_EQ(request, cur_request_.get());
@@ -157,7 +157,7 @@ void ProxyScriptFetcherImpl::OnSSLCertificateError(URLRequest* request,
request->Cancel();
}
-void ProxyScriptFetcherImpl::OnResponseStarted(URLRequest* request) {
+void ProxyScriptFetcherImpl::OnResponseStarted(net::URLRequest* request) {
DCHECK_EQ(request, cur_request_.get());
if (!request->status().is_success()) {
@@ -191,7 +191,7 @@ void ProxyScriptFetcherImpl::OnResponseStarted(URLRequest* request) {
ReadBody(request);
}
-void ProxyScriptFetcherImpl::OnReadCompleted(URLRequest* request,
+void ProxyScriptFetcherImpl::OnReadCompleted(net::URLRequest* request,
int num_bytes) {
DCHECK_EQ(request, cur_request_.get());
if (ConsumeBytesRead(request, num_bytes)) {
@@ -200,7 +200,7 @@ void ProxyScriptFetcherImpl::OnReadCompleted(URLRequest* request,
}
}
-void ProxyScriptFetcherImpl::OnResponseCompleted(URLRequest* request) {
+void ProxyScriptFetcherImpl::OnResponseCompleted(net::URLRequest* request) {
DCHECK_EQ(request, cur_request_.get());
// Use |result_code_| as the request's error if we have already set it to
@@ -211,7 +211,7 @@ void ProxyScriptFetcherImpl::OnResponseCompleted(URLRequest* request) {
FetchCompleted();
}
-void ProxyScriptFetcherImpl::ReadBody(URLRequest* request) {
+void ProxyScriptFetcherImpl::ReadBody(net::URLRequest* request) {
// Read as many bytes as are available synchronously.
while (true) {
int num_bytes;
@@ -226,7 +226,7 @@ void ProxyScriptFetcherImpl::ReadBody(URLRequest* request) {
}
}
-bool ProxyScriptFetcherImpl::ConsumeBytesRead(URLRequest* request,
+bool ProxyScriptFetcherImpl::ConsumeBytesRead(net::URLRequest* request,
int num_bytes) {
if (num_bytes <= 0) {
// Error while reading, or EOF.
@@ -277,7 +277,7 @@ void ProxyScriptFetcherImpl::ResetCurRequestState() {
}
void ProxyScriptFetcherImpl::OnTimeout(int id) {
- // Timeout tasks may outlive the URLRequest they reference. Make sure it
+ // Timeout tasks may outlive the net::URLRequest they reference. Make sure it
// is still applicable.
if (cur_request_id_ != id)
return;
diff --git a/net/proxy/proxy_script_fetcher_impl.h b/net/proxy/proxy_script_fetcher_impl.h
index b671f6d..4461650 100644
--- a/net/proxy/proxy_script_fetcher_impl.h
+++ b/net/proxy/proxy_script_fetcher_impl.h
@@ -24,7 +24,7 @@ namespace net {
// Implementation of ProxyScriptFetcher that downloads scripts using the
// specified request context.
class ProxyScriptFetcherImpl : public ProxyScriptFetcher,
- public URLRequest::Delegate {
+ public net::URLRequest::Delegate {
public:
// Creates a ProxyScriptFetcher that issues requests through
// |url_request_context|. |url_request_context| must remain valid for the
@@ -43,15 +43,14 @@ class ProxyScriptFetcherImpl : public ProxyScriptFetcher,
virtual void Cancel();
virtual URLRequestContext* GetRequestContext();
- // URLRequest::Delegate methods:
-
- virtual void OnAuthRequired(URLRequest* request,
+ // net::URLRequest::Delegate methods:
+ virtual void OnAuthRequired(net::URLRequest* request,
AuthChallengeInfo* auth_info);
- virtual void OnSSLCertificateError(URLRequest* request, int cert_error,
+ virtual void OnSSLCertificateError(net::URLRequest* request, int cert_error,
X509Certificate* cert);
- virtual void OnResponseStarted(URLRequest* request);
- virtual void OnReadCompleted(URLRequest* request, int num_bytes);
- virtual void OnResponseCompleted(URLRequest* request);
+ virtual void OnResponseStarted(net::URLRequest* request);
+ virtual void OnReadCompleted(net::URLRequest* request, int num_bytes);
+ virtual void OnResponseCompleted(net::URLRequest* request);
// Used by unit-tests to modify the default limits.
base::TimeDelta SetTimeoutConstraint(base::TimeDelta timeout);
@@ -59,11 +58,11 @@ class ProxyScriptFetcherImpl : public ProxyScriptFetcher,
private:
// Read more bytes from the response.
- void ReadBody(URLRequest* request);
+ void ReadBody(net::URLRequest* request);
// Handles a response from Read(). Returns true if we should continue trying
// to read. |num_bytes| is 0 for EOF, and < 0 on errors.
- bool ConsumeBytesRead(URLRequest* request, int num_bytes);
+ bool ConsumeBytesRead(net::URLRequest* request, int num_bytes);
// Called once the request has completed to notify the caller of
// |response_code_| and |response_text_|.
@@ -82,7 +81,7 @@ class ProxyScriptFetcherImpl : public ProxyScriptFetcher,
// The context used for making network requests.
URLRequestContext* url_request_context_;
- // Buffer that URLRequest writes into.
+ // Buffer that net::URLRequest writes into.
enum { kBufSize = 4096 };
scoped_refptr<net::IOBuffer> buf_;
@@ -90,7 +89,7 @@ class ProxyScriptFetcherImpl : public ProxyScriptFetcher,
int next_id_;
// The current (in progress) request, or NULL.
- scoped_ptr<URLRequest> cur_request_;
+ scoped_ptr<net::URLRequest> cur_request_;
// State for current request (only valid when |cur_request_| is not NULL):
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index 347bbe9..ec0fb58 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -39,18 +39,21 @@ class RequestContext : public URLRequestContext {
host_resolver_ =
net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
NULL, NULL);
+ cert_verifier_ = new net::CertVerifier;
proxy_service_ = net::ProxyService::CreateFixed(no_proxy);
ssl_config_service_ = new net::SSLConfigServiceDefaults;
http_transaction_factory_ = new net::HttpCache(
- net::HttpNetworkLayer::CreateFactory(host_resolver_, NULL, NULL, NULL,
- proxy_service_, ssl_config_service_, NULL, NULL, NULL),
+ net::HttpNetworkLayer::CreateFactory(host_resolver_, cert_verifier_,
+ NULL, NULL, NULL, proxy_service_, ssl_config_service_, NULL, NULL,
+ NULL),
net::HttpCache::DefaultBackend::InMemory(0));
}
private:
~RequestContext() {
delete http_transaction_factory_;
+ delete cert_verifier_;
delete host_resolver_;
}
};
@@ -76,7 +79,7 @@ class ProxyScriptFetcherImplTest : public PlatformTest {
}
static void SetUpTestCase() {
- URLRequest::AllowFileAccess();
+ net::URLRequest::AllowFileAccess();
}
protected:
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index b4aa96d..d7fa0ef 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -12,7 +12,6 @@
#include "base/message_loop.h"
#include "base/string_util.h"
#include "googleurl/src/gurl.h"
-#include "net/base/forwarding_net_log.h"
#include "net/base/net_log.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
@@ -127,6 +126,10 @@ class ProxyResolverNull : public ProxyResolver {
NOTREACHED();
}
+ virtual void CancelSetPacScript() {
+ NOTREACHED();
+ }
+
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& /*script_data*/,
CompletionCallback* /*callback*/) {
@@ -155,6 +158,10 @@ class ProxyResolverFromPacString : public ProxyResolver {
NOTREACHED();
}
+ virtual void CancelSetPacScript() {
+ NOTREACHED();
+ }
+
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& pac_script,
CompletionCallback* callback) {
@@ -170,16 +177,14 @@ class ProxyResolverFactoryForV8 : public ProxyResolverFactory {
public:
// |async_host_resolver|, |io_loop| and |net_log| must remain
// valid for the duration of our lifetime.
- // Both |async_host_resolver| and |net_log| will only be operated on
- // |io_loop|.
+ // |async_host_resolver| will only be operated on |io_loop|.
ProxyResolverFactoryForV8(HostResolver* async_host_resolver,
MessageLoop* io_loop,
NetLog* net_log)
: ProxyResolverFactory(true /*expects_pac_bytes*/),
async_host_resolver_(async_host_resolver),
io_loop_(io_loop),
- forwarding_net_log_(
- net_log ? new ForwardingNetLog(net_log, io_loop) : NULL) {
+ net_log_(net_log) {
}
virtual ProxyResolver* CreateProxyResolver() {
@@ -189,8 +194,7 @@ class ProxyResolverFactoryForV8 : public ProxyResolverFactory {
new SyncHostResolverBridge(async_host_resolver_, io_loop_);
ProxyResolverJSBindings* js_bindings =
- ProxyResolverJSBindings::CreateDefault(sync_host_resolver,
- forwarding_net_log_.get());
+ ProxyResolverJSBindings::CreateDefault(sync_host_resolver, net_log_);
// ProxyResolverV8 takes ownership of |js_bindings|.
return new ProxyResolverV8(js_bindings);
@@ -199,10 +203,7 @@ class ProxyResolverFactoryForV8 : public ProxyResolverFactory {
private:
HostResolver* const async_host_resolver_;
MessageLoop* io_loop_;
-
- // Thread-safe wrapper around a non-threadsafe NetLog implementation. This
- // enables the proxy resolver to emit log messages from the PAC thread.
- scoped_ptr<ForwardingNetLog> forwarding_net_log_;
+ NetLog* net_log_;
};
// Creates ProxyResolvers using a platform-specific implementation.
@@ -480,9 +481,13 @@ ProxyService* ProxyService::CreateFixed(const std::string& proxy) {
// static
ProxyService* ProxyService::CreateDirect() {
+ return CreateDirectWithNetLog(NULL);
+}
+
+ProxyService* ProxyService::CreateDirectWithNetLog(NetLog* net_log) {
// Use direct connections.
return new ProxyService(new ProxyConfigServiceDirect, new ProxyResolverNull,
- NULL);
+ net_log);
}
// static
diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h
index 8a161ea..ba56f4d 100644
--- a/net/proxy/proxy_service.h
+++ b/net/proxy/proxy_service.h
@@ -193,6 +193,8 @@ class ProxyService : public base::RefCountedThreadSafe<ProxyService>,
// Creates a proxy service that uses a DIRECT connection for all requests.
static ProxyService* CreateDirect();
+ // |net_log|'s lifetime must exceed ProxyService.
+ static ProxyService* CreateDirectWithNetLog(NetLog* net_log);
// This method is used by tests to create a ProxyService that returns a
// hardcoded proxy fallback list (|pac_string|) for every URL.
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc
index 1c77876..7dec769 100644
--- a/net/proxy/proxy_service_unittest.cc
+++ b/net/proxy/proxy_service_unittest.cc
@@ -98,6 +98,8 @@ class MockProxyScriptFetcher : public ProxyScriptFetcher {
virtual void Cancel() {}
+ virtual URLRequestContext* GetRequestContext() { return NULL; }
+
const GURL& pending_request_url() const {
return pending_request_url_;
}
@@ -130,14 +132,17 @@ TEST(ProxyServiceTest, Direct) {
EXPECT_TRUE(info.is_direct());
// Check the NetLog was filled correctly.
- EXPECT_EQ(3u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(3u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_PROXY_SERVICE));
+ entries, 0, NetLog::TYPE_PROXY_SERVICE));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
+ entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_PROXY_SERVICE));
+ entries, 2, NetLog::TYPE_PROXY_SERVICE));
}
TEST(ProxyServiceTest, PAC) {
@@ -174,15 +179,18 @@ TEST(ProxyServiceTest, PAC) {
EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
// Check the NetLog was filled correctly.
- EXPECT_EQ(5u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(5u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_PROXY_SERVICE));
+ entries, 0, NetLog::TYPE_PROXY_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
+ entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
+ entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 4, NetLog::TYPE_PROXY_SERVICE));
+ entries, 4, NetLog::TYPE_PROXY_SERVICE));
}
// Test that the proxy resolver does not see the URL's username/password
@@ -1149,18 +1157,21 @@ TEST(ProxyServiceTest, CancelWhilePACFetching) {
EXPECT_FALSE(callback1.have_result()); // Cancelled.
EXPECT_FALSE(callback2.have_result()); // Cancelled.
+ net::CapturingNetLog::EntryList entries1;
+ log1.GetEntries(&entries1);
+
// Check the NetLog for request 1 (which was cancelled) got filled properly.
- EXPECT_EQ(4u, log1.entries().size());
+ EXPECT_EQ(4u, entries1.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log1.entries(), 0, NetLog::TYPE_PROXY_SERVICE));
+ entries1, 0, NetLog::TYPE_PROXY_SERVICE));
EXPECT_TRUE(LogContainsBeginEvent(
- log1.entries(), 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
+ entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
// Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
// the cancellation occured.
EXPECT_TRUE(LogContainsEvent(
- log1.entries(), 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
+ entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
- log1.entries(), 3, NetLog::TYPE_PROXY_SERVICE));
+ entries1, 3, NetLog::TYPE_PROXY_SERVICE));
}
// Test that if auto-detect fails, we fall-back to the custom pac.
@@ -1679,11 +1690,14 @@ TEST(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
// In particular, PROXY_CONFIG_CHANGED should have only been emitted once
// (for the initial setup), and NOT a second time when the IP address
// changed.
- EXPECT_TRUE(LogContainsEntryWithType(log.entries(), 0,
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
NetLog::TYPE_PROXY_CONFIG_CHANGED));
- ASSERT_EQ(13u, log.entries().size());
- for (size_t i = 1; i < log.entries().size(); ++i)
- EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, log.entries()[i].type);
+ ASSERT_EQ(13u, entries.size());
+ for (size_t i = 1; i < entries.size(); ++i)
+ EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
}
} // namespace net
diff --git a/net/proxy/sync_host_resolver_bridge_unittest.cc b/net/proxy/sync_host_resolver_bridge_unittest.cc
index cd4264e..43c829f 100644
--- a/net/proxy/sync_host_resolver_bridge_unittest.cc
+++ b/net/proxy/sync_host_resolver_bridge_unittest.cc
@@ -109,6 +109,10 @@ class SyncProxyResolver : public ProxyResolver {
host_resolver_->Shutdown();
}
+ virtual void CancelSetPacScript() {
+ NOTREACHED();
+ }
+
virtual int SetPacScript(
const scoped_refptr<ProxyResolverScriptData>& script_data,
CompletionCallback* callback) {
diff --git a/net/server/http_listen_socket.cc b/net/server/http_listen_socket.cc
index f35582b..a946bd9 100644
--- a/net/server/http_listen_socket.cc
+++ b/net/server/http_listen_socket.cc
@@ -310,6 +310,14 @@ bool HttpListenSocket::ParseHeaders(HttpServerRequestInfo* info) {
return false;
}
+void HttpListenSocket::Close() {
+ ListenSocket::Close();
+}
+
+void HttpListenSocket::Listen() {
+ ListenSocket::Listen();
+}
+
void HttpListenSocket::DidAccept(ListenSocket* server,
ListenSocket* connection) {
connection->AddRef();
@@ -344,6 +352,6 @@ void HttpListenSocket::DidRead(ListenSocket*,
}
void HttpListenSocket::DidClose(ListenSocket* sock) {
- sock->Release();
delegate_->OnClose(this);
+ sock->Release();
}
diff --git a/net/server/http_listen_socket.h b/net/server/http_listen_socket.h
index 2eae47d..8b0bbc2 100644
--- a/net/server/http_listen_socket.h
+++ b/net/server/http_listen_socket.h
@@ -44,8 +44,8 @@ class HttpListenSocket : public ListenSocket,
void Send404();
void Send500(const std::string& message);
- void Close() { ListenSocket::Close(); }
- void Listen() { ListenSocket::Listen(); }
+ virtual void Close();
+ virtual void Listen();
// ListenSocketDelegate
virtual void DidAccept(ListenSocket* server, ListenSocket* connection);
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 8965630..f4da066 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -4,7 +4,7 @@
#include "net/socket/client_socket_factory.h"
-#include "base/singleton.h"
+#include "base/lazy_instance.h"
#include "build/build_config.h"
#include "net/socket/client_socket_handle.h"
#if defined(OS_WIN)
@@ -30,19 +30,21 @@ SSLClientSocket* DefaultSSLClientSocketFactory(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
scoped_ptr<SSLHostInfo> shi(ssl_host_info);
#if defined(OS_WIN)
- return new SSLClientSocketWin(transport_socket, host_and_port, ssl_config);
+ return new SSLClientSocketWin(transport_socket, host_and_port, ssl_config,
+ cert_verifier);
#elif defined(USE_OPENSSL)
return new SSLClientSocketOpenSSL(transport_socket, host_and_port,
- ssl_config);
+ ssl_config, cert_verifier);
#elif defined(USE_NSS)
return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config,
- shi.release(), dns_cert_checker);
+ shi.release(), cert_verifier, dns_cert_checker);
#elif defined(OS_MACOSX)
return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config,
- shi.release(), dns_cert_checker);
+ shi.release(), cert_verifier, dns_cert_checker);
#else
NOTIMPLEMENTED();
return NULL;
@@ -65,17 +67,21 @@ class DefaultClientSocketFactory : public ClientSocketFactory {
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
return g_ssl_factory(transport_socket, host_and_port, ssl_config,
- ssl_host_info, dns_cert_checker);
+ ssl_host_info, cert_verifier, dns_cert_checker);
}
};
+static base::LazyInstance<DefaultClientSocketFactory>
+ g_default_client_socket_factory(base::LINKER_INITIALIZED);
+
} // namespace
// static
ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() {
- return Singleton<DefaultClientSocketFactory>::get();
+ return g_default_client_socket_factory.Pointer();
}
// static
@@ -89,11 +95,12 @@ SSLClientSocket* ClientSocketFactory::CreateSSLClientSocket(
ClientSocket* transport_socket,
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info) {
+ SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier) {
ClientSocketHandle* socket_handle = new ClientSocketHandle();
socket_handle->set_socket(transport_socket);
return CreateSSLClientSocket(socket_handle, host_and_port, ssl_config,
- ssl_host_info,
+ ssl_host_info, cert_verifier,
NULL /* DnsCertProvenanceChecker */);
}
diff --git a/net/socket/client_socket_factory.h b/net/socket/client_socket_factory.h
index 0ab370a..2a0cd7c 100644
--- a/net/socket/client_socket_factory.h
+++ b/net/socket/client_socket_factory.h
@@ -14,6 +14,7 @@
namespace net {
class AddressList;
+class CertVerifier;
class ClientSocket;
class ClientSocketHandle;
class DnsCertProvenanceChecker;
@@ -28,6 +29,7 @@ typedef SSLClientSocket* (*SSLClientSocketFactory)(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker);
// An interface used to instantiate ClientSocket objects. Used to facilitate
@@ -48,6 +50,7 @@ class ClientSocketFactory {
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) = 0;
// Deprecated function (http://crbug.com/37810) that takes a ClientSocket.
@@ -55,7 +58,8 @@ class ClientSocketFactory {
ClientSocket* transport_socket,
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info);
+ SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier);
// Returns the default ClientSocketFactory.
static ClientSocketFactory* GetDefaultFactory();
diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h
index 23bb63f..c889ab4 100644
--- a/net/socket/client_socket_pool.h
+++ b/net/socket/client_socket_pool.h
@@ -45,8 +45,8 @@ class ClientSocketPool {
// The caller must recover from the error before using the connection, or
// Disconnect the socket before releasing or resetting the |handle|.
// The current recoverable errors are: the errors accepted by
- // IsCertificateError(err) and PROXY_AUTH_REQUESTED when reported by
- // HttpProxyClientSocketPool.
+ // IsCertificateError(err) and PROXY_AUTH_REQUESTED, or
+ // HTTPS_PROXY_TUNNEL_RESPONSE when reported by HttpProxyClientSocketPool.
//
// If this function returns OK, then |handle| is initialized upon return.
// The |handle|'s is_initialized method will return true in this case. If a
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 9cbefa9..871966f 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -359,12 +359,8 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal(
group->AddJob(connect_job.release());
} else {
LogBoundConnectJobToRequest(connect_job->net_log().source(), request);
- ClientSocket* error_socket = NULL;
- if (!preconnecting) {
- DCHECK(handle);
- connect_job->GetAdditionalErrorState(handle);
- error_socket = connect_job->ReleaseSocket();
- }
+ connect_job->GetAdditionalErrorState(handle);
+ ClientSocket* error_socket = connect_job->ReleaseSocket();
if (error_socket) {
HandOutSocket(error_socket, false /* not reused */, handle,
base::TimeDelta(), group, request->net_log());
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 0d8827e..7c0e2e1 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -110,6 +110,7 @@ class MockClientSocketFactory : public ClientSocketFactory {
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
NOTIMPLEMENTED();
delete ssl_host_info;
@@ -620,21 +621,24 @@ TEST_F(ClientSocketPoolBaseTest, ConnectJob_TimedOut) {
PlatformThread::Sleep(1);
EXPECT_EQ(ERR_TIMED_OUT, delegate.WaitForResult());
- EXPECT_EQ(6u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(6u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB));
+ entries, 0, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB));
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 1, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT));
+ entries, 1, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 2, NetLog::TYPE_CONNECT_JOB_SET_SOCKET,
+ entries, 2, NetLog::TYPE_CONNECT_JOB_SET_SOCKET,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 3, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_TIMED_OUT,
+ entries, 3, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_TIMED_OUT,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 4, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT));
+ entries, 4, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 5, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB));
+ entries, 5, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB));
}
TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
@@ -655,17 +659,20 @@ TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
EXPECT_TRUE(handle.socket());
handle.Reset();
- EXPECT_EQ(4u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(4u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
+ entries, 0, NetLog::TYPE_SOCKET_POOL));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
+ entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
+ entries, 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 3, NetLog::TYPE_SOCKET_POOL));
+ entries, 3, NetLog::TYPE_SOCKET_POOL));
}
TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
@@ -692,14 +699,17 @@ TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
EXPECT_FALSE(handle.is_ssl_error());
EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL);
- EXPECT_EQ(3u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(3u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
+ entries, 0, NetLog::TYPE_SOCKET_POOL));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
+ entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_SOCKET_POOL));
+ entries, 2, NetLog::TYPE_SOCKET_POOL));
}
TEST_F(ClientSocketPoolBaseTest, TotalLimit) {
@@ -1503,17 +1513,20 @@ TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) {
EXPECT_TRUE(handle.socket());
handle.Reset();
- EXPECT_EQ(4u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(4u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
+ entries, 0, NetLog::TYPE_SOCKET_POOL));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
+ entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
+ entries, 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 3, NetLog::TYPE_SOCKET_POOL));
+ entries, 3, NetLog::TYPE_SOCKET_POOL));
}
TEST_F(ClientSocketPoolBaseTest,
@@ -1540,14 +1553,17 @@ TEST_F(ClientSocketPoolBaseTest,
EXPECT_FALSE(handle.is_ssl_error());
EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL);
- EXPECT_EQ(3u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_EQ(3u, entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
+ entries, 0, NetLog::TYPE_SOCKET_POOL));
EXPECT_TRUE(LogContainsEvent(
- log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
+ entries, 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), 2, NetLog::TYPE_SOCKET_POOL));
+ entries, 2, NetLog::TYPE_SOCKET_POOL));
}
TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
@@ -1892,8 +1908,11 @@ TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSockets) {
log.bound());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_reused());
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEntryWithType(
- log.entries(), 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET));
+ entries, 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET));
}
// Make sure that we process all pending requests even when we're stalling
@@ -2906,13 +2925,6 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsSynchronousError) {
BoundNetLog());
ASSERT_FALSE(pool_->HasGroup("a"));
-
- connect_job_factory_->set_job_type(
- TestConnectJob::kMockAdditionalErrorStateJob);
- pool_->RequestSockets("a", &params_, kDefaultMaxSocketsPerGroup,
- BoundNetLog());
-
- ASSERT_FALSE(pool_->HasGroup("a"));
}
TEST_F(ClientSocketPoolBaseTest, RequestSocketsMultipleTimesDoesNothing) {
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index 6c73c36..8516fbc 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -55,6 +55,7 @@ ClientSocketPoolManager::ClientSocketPoolManager(
NetLog* net_log,
ClientSocketFactory* socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -63,6 +64,7 @@ ClientSocketPoolManager::ClientSocketPoolManager(
: net_log_(net_log),
socket_factory_(socket_factory),
host_resolver_(host_resolver),
+ cert_verifier_(cert_verifier),
dnsrr_resolver_(dnsrr_resolver),
dns_cert_checker_(dns_cert_checker),
ssl_host_info_factory_(ssl_host_info_factory),
@@ -80,6 +82,7 @@ ClientSocketPoolManager::ClientSocketPoolManager(
g_max_sockets, g_max_sockets_per_group,
&ssl_pool_histograms_,
host_resolver,
+ cert_verifier,
dnsrr_resolver,
dns_cert_checker,
ssl_host_info_factory,
@@ -230,6 +233,7 @@ HttpProxyClientSocketPool* ClientSocketPoolManager::GetSocketPoolForHTTPProxy(
g_max_sockets_per_proxy_server, g_max_sockets_per_group,
&ssl_for_https_proxy_pool_histograms_,
host_resolver_,
+ cert_verifier_,
dnsrr_resolver_,
dns_cert_checker_,
ssl_host_info_factory_,
@@ -266,6 +270,7 @@ SSLClientSocketPool* ClientSocketPoolManager::GetSocketPoolForSSLWithProxy(
g_max_sockets_per_proxy_server, g_max_sockets_per_group,
&ssl_pool_histograms_,
host_resolver_,
+ cert_verifier_,
dnsrr_resolver_,
dns_cert_checker_,
ssl_host_info_factory_,
diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h
index 823213e..cfcb465 100644
--- a/net/socket/client_socket_pool_manager.h
+++ b/net/socket/client_socket_pool_manager.h
@@ -6,8 +6,8 @@
// simple container for all of them. Most importantly, it handles the lifetime
// and destruction order properly.
-#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_
-#define NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_
+#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_H_
+#define NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_H_
#pragma once
#include <map>
@@ -23,6 +23,7 @@ class Value;
namespace net {
+class CertVerifier;
class ClientSocketFactory;
class ClientSocketPoolHistograms;
class DnsCertProvenanceChecker;
@@ -54,13 +55,14 @@ class OwnedPoolMap : public std::map<Key, Value> {
}
};
-} // internal
+} // namespace internal
class ClientSocketPoolManager : public NonThreadSafe {
public:
ClientSocketPoolManager(NetLog* net_log,
ClientSocketFactory* socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -106,6 +108,7 @@ class ClientSocketPoolManager : public NonThreadSafe {
NetLog* const net_log_;
ClientSocketFactory* const socket_factory_;
HostResolver* const host_resolver_;
+ CertVerifier* const cert_verifier_;
DnsRRResolver* const dnsrr_resolver_;
DnsCertProvenanceChecker* const dns_cert_checker_;
SSLHostInfoFactory* const ssl_host_info_factory_;
@@ -146,4 +149,4 @@ class ClientSocketPoolManager : public NonThreadSafe {
} // namespace net
-#endif // NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_
+#endif // NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_H_
diff --git a/net/socket/dns_cert_provenance_checker.cc b/net/socket/dns_cert_provenance_checker.cc
index 27c4982..51a9750 100644
--- a/net/socket/dns_cert_provenance_checker.cc
+++ b/net/socket/dns_cert_provenance_checker.cc
@@ -16,13 +16,14 @@
#include <set>
#include <string>
+#include "base/base64.h"
#include "base/basictypes.h"
#include "base/crypto/encryptor.h"
#include "base/crypto/symmetric_key.h"
+#include "base/lazy_instance.h"
#include "base/non_thread_safe.h"
#include "base/pickle.h"
#include "base/scoped_ptr.h"
-#include "base/singleton.h"
#include "net/base/completion_callback.h"
#include "net/base/dns_util.h"
#include "net/base/dnsrr_resolver.h"
@@ -72,13 +73,16 @@ class DnsCertLimits {
}
private:
- friend struct DefaultSingletonTraits<DnsCertLimits>;
+ friend struct base::DefaultLazyInstanceTraits<DnsCertLimits>;
std::set<std::string> uploaded_hostnames_;
DISALLOW_COPY_AND_ASSIGN(DnsCertLimits);
};
+static base::LazyInstance<DnsCertLimits> g_dns_cert_limits(
+ base::LINKER_INITIALIZED);
+
// DnsCertProvenanceCheck performs the DNS lookup of the certificate. This
// class is self-deleting.
class DnsCertProvenanceCheck : public NonThreadSafe {
@@ -105,7 +109,7 @@ class DnsCertProvenanceCheck : public NonThreadSafe {
if (der_certs_.empty())
return;
- DnsCertLimits* const limits = Singleton<DnsCertLimits>::get();
+ DnsCertLimits* const limits = g_dns_cert_limits.Pointer();
if (limits->HaveReachedMaxUploads() ||
limits->HaveUploadedForHostname(hostname_)) {
return;
@@ -124,7 +128,7 @@ class DnsCertProvenanceCheck : public NonThreadSafe {
}
fingerprint_hex[SHA1_LENGTH * 2] = 0;
- static const char kBaseCertName[] = ".certs.links.org";
+ static const char kBaseCertName[] = ".certs.googlednstest.com";
domain_.assign(fingerprint_hex);
domain_.append(kBaseCertName);
@@ -146,7 +150,8 @@ class DnsCertProvenanceCheck : public NonThreadSafe {
LOG(ERROR) << "FAILED"
<< " hostname:" << hostname_
<< " domain:" << domain_;
- Singleton<DnsCertLimits>::get()->DidUpload(hostname_);
+ g_dns_cert_limits.Get().DidUpload(hostname_);
+ LogCertificates(der_certs_);
delegate_->OnDnsCertLookupFailed(hostname_, der_certs_);
} else if (status == OK) {
LOG(ERROR) << "GOOD"
@@ -159,6 +164,35 @@ class DnsCertProvenanceCheck : public NonThreadSafe {
delete this;
}
+ // LogCertificates writes a certificate chain, in PEM format, to LOG(ERROR).
+ static void LogCertificates(
+ const std::vector<std::string>& der_certs) {
+ std::string dump;
+ bool first = true;
+
+ for (std::vector<std::string>::const_iterator
+ i = der_certs.begin(); i != der_certs.end(); i++) {
+ if (!first)
+ dump += "\n";
+ first = false;
+
+ dump += "-----BEGIN CERTIFICATE-----\n";
+ std::string b64_encoded;
+ base::Base64Encode(*i, &b64_encoded);
+ for (size_t i = 0; i < b64_encoded.size();) {
+ size_t todo = b64_encoded.size() - i;
+ if (todo > 64)
+ todo = 64;
+ dump += b64_encoded.substr(i, todo);
+ dump += "\n";
+ i += todo;
+ }
+ dump += "-----END CERTIFICATE-----";
+ }
+
+ LOG(ERROR) << "Offending certificates:\n" << dump;
+ }
+
const std::string hostname_;
std::string domain_;
DnsRRResolver* dnsrr_resolver_;
diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc
new file mode 100644
index 0000000..eb8bafb
--- /dev/null
+++ b/net/socket/nss_ssl_util.cc
@@ -0,0 +1,240 @@
+// 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/nss_ssl_util.h"
+
+#include <nss.h>
+#include <secerr.h>
+#include <ssl.h>
+#include <sslerr.h>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/nss_util.h"
+#include "base/singleton.h"
+#include "base/thread_restrictions.h"
+#include "base/values.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+
+namespace net {
+
+class NSSSSLInitSingleton {
+ public:
+ NSSSSLInitSingleton() {
+ base::EnsureNSSInit();
+
+ NSS_SetDomesticPolicy();
+
+#if defined(USE_SYSTEM_SSL)
+ // Use late binding to avoid scary but benign warning
+ // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
+ // consider re-linking"
+ // TODO(wtc): Use the new SSL_GetImplementedCiphers and
+ // SSL_GetNumImplementedCiphers functions when we require NSS 3.12.6.
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=496993.
+ const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
+ dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
+ if (pSSL_ImplementedCiphers == NULL) {
+ NOTREACHED() << "Can't get list of supported ciphers";
+ return;
+ }
+#else
+#define pSSL_ImplementedCiphers SSL_ImplementedCiphers
+#endif
+
+ // Explicitly enable exactly those ciphers with keys of at least 80 bits
+ for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
+ SSLCipherSuiteInfo info;
+ if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
+ sizeof(info)) == SECSuccess) {
+ SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
+ (info.effectiveKeyBits >= 80));
+ }
+ }
+
+ // Enable SSL.
+ SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
+
+ // All other SSL options are set per-session by SSLClientSocket and
+ // SSLServerSocket.
+ }
+
+ ~NSSSSLInitSingleton() {
+ // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
+ SSL_ClearSessionCache();
+ }
+};
+
+static base::LazyInstance<NSSSSLInitSingleton> g_nss_ssl_init_singleton(
+ base::LINKER_INITIALIZED);
+
+// Initialize the NSS SSL library if it isn't already initialized. This must
+// be called before any other NSS SSL functions. This function is
+// 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;
+
+ g_nss_ssl_init_singleton.Get();
+}
+
+// Map a Chromium net error code to an NSS error code.
+// See _MD_unix_map_default_error in the NSS source
+// tree for inspiration.
+PRErrorCode MapErrorToNSS(int result) {
+ if (result >=0)
+ return result;
+
+ switch (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:
+ case ERR_TIMED_OUT:
+ return PR_IO_TIMEOUT_ERROR;
+ case ERR_CONNECTION_RESET:
+ return PR_CONNECT_RESET_ERROR;
+ case ERR_CONNECTION_ABORTED:
+ return PR_CONNECT_ABORTED_ERROR;
+ case ERR_CONNECTION_REFUSED:
+ return PR_CONNECT_REFUSED_ERROR;
+ case ERR_ADDRESS_UNREACHABLE:
+ return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR.
+ case ERR_ADDRESS_INVALID:
+ return PR_ADDRESS_NOT_AVAILABLE_ERROR;
+ case ERR_NAME_NOT_RESOLVED:
+ return PR_DIRECTORY_LOOKUP_ERROR;
+ default:
+ LOG(WARNING) << "MapErrorToNSS " << result
+ << " mapped to PR_UNKNOWN_ERROR";
+ return PR_UNKNOWN_ERROR;
+ }
+}
+
+// The default error mapping function.
+// Maps an NSS error code to a network error code.
+int MapNSSError(PRErrorCode err) {
+ // TODO(port): fill this out as we learn what's important
+ switch (err) {
+ case PR_WOULD_BLOCK_ERROR:
+ return ERR_IO_PENDING;
+ case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect.
+ case PR_NO_ACCESS_RIGHTS_ERROR:
+ return ERR_ACCESS_DENIED;
+ case PR_IO_TIMEOUT_ERROR:
+ return ERR_TIMED_OUT;
+ case PR_CONNECT_RESET_ERROR:
+ return ERR_CONNECTION_RESET;
+ case PR_CONNECT_ABORTED_ERROR:
+ return ERR_CONNECTION_ABORTED;
+ case PR_CONNECT_REFUSED_ERROR:
+ return ERR_CONNECTION_REFUSED;
+ case PR_HOST_UNREACHABLE_ERROR:
+ case PR_NETWORK_UNREACHABLE_ERROR:
+ return ERR_ADDRESS_UNREACHABLE;
+ case PR_ADDRESS_NOT_AVAILABLE_ERROR:
+ return ERR_ADDRESS_INVALID;
+ case PR_INVALID_ARGUMENT_ERROR:
+ 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;
+
+ case SSL_ERROR_SSL_DISABLED:
+ return ERR_NO_SSL_VERSIONS_ENABLED;
+ case SSL_ERROR_NO_CYPHER_OVERLAP:
+ case SSL_ERROR_UNSUPPORTED_VERSION:
+ return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
+ case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
+ case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
+ case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
+ return ERR_SSL_PROTOCOL_ERROR;
+ case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT:
+ return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
+ case SSL_ERROR_BAD_MAC_ALERT:
+ return ERR_SSL_BAD_RECORD_MAC_ALERT;
+ case SSL_ERROR_UNSAFE_NEGOTIATION:
+ return ERR_SSL_UNSAFE_NEGOTIATION;
+ case SSL_ERROR_WEAK_SERVER_KEY:
+ return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
+
+ default: {
+ if (IS_SSL_ERROR(err)) {
+ LOG(WARNING) << "Unknown SSL error " << err <<
+ " mapped to net::ERR_SSL_PROTOCOL_ERROR";
+ return ERR_SSL_PROTOCOL_ERROR;
+ }
+ LOG(WARNING) << "Unknown error " << err <<
+ " mapped to net::ERR_FAILED";
+ return ERR_FAILED;
+ }
+ }
+}
+
+// Context-sensitive error mapping functions.
+int MapNSSHandshakeError(PRErrorCode err) {
+ switch (err) {
+ // If the server closed on us, it is a protocol error.
+ // Some TLS-intolerant servers do this when we request TLS.
+ case PR_END_OF_FILE_ERROR:
+ // The handshake may fail because some signature (for example, the
+ // signature in the ServerKeyExchange message for an ephemeral
+ // Diffie-Hellman cipher suite) is invalid.
+ case SEC_ERROR_BAD_SIGNATURE:
+ return ERR_SSL_PROTOCOL_ERROR;
+ default:
+ return MapNSSError(err);
+ }
+}
+
+// Extra parameters to attach to the NetLog when we receive an error in response
+// to a call to an NSS function. Used instead of SSLErrorParams with
+// events of type TYPE_SSL_NSS_ERROR. Automatically looks up last PR error.
+class SSLFailedNSSFunctionParams : public NetLog::EventParameters {
+ public:
+ // |param| is ignored if it has a length of 0.
+ SSLFailedNSSFunctionParams(const std::string& function,
+ const std::string& param)
+ : function_(function), param_(param), ssl_lib_error_(PR_GetError()) {
+ }
+
+ virtual Value* ToValue() const {
+ DictionaryValue* dict = new DictionaryValue();
+ dict->SetString("function", function_);
+ if (!param_.empty())
+ dict->SetString("param", param_);
+ dict->SetInteger("ssl_lib_error", ssl_lib_error_);
+ return dict;
+ }
+
+ private:
+ const std::string function_;
+ const std::string param_;
+ const PRErrorCode ssl_lib_error_;
+};
+
+void LogFailedNSSFunction(const BoundNetLog& net_log,
+ const char* function,
+ const char* param) {
+ net_log.AddEvent(
+ NetLog::TYPE_SSL_NSS_ERROR,
+ make_scoped_refptr(new SSLFailedNSSFunctionParams(function, param)));
+}
+
+} // namespace net
diff --git a/net/socket/nss_ssl_util.h b/net/socket/nss_ssl_util.h
new file mode 100644
index 0000000..64bf3cf
--- /dev/null
+++ b/net/socket/nss_ssl_util.h
@@ -0,0 +1,36 @@
+// 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.
+
+// This file is only inclued in ssl_client_socket_nss.cc and
+// ssl_server_socket_nss.cc to share common functions of NSS.
+
+#ifndef NET_SOCKET_NSS_SSL_UTIL_H_
+#define NEt_SOCKET_NSS_SSL_UTIL_H_
+
+#include <prerror.h>
+
+namespace net {
+
+class BoundNetLog;
+
+// Initalize NSS SSL library.
+void EnsureNSSSSLInit();
+
+// Log a failed NSS funcion call.
+void LogFailedNSSFunction(const BoundNetLog& net_log,
+ const char* function,
+ const char* param);
+
+// Map network error code to NSS error code.
+PRErrorCode MapErrorToNSS(int result);
+
+// Map NSS error code to network error code.
+int MapNSSError(PRErrorCode err);
+
+// Map NSS handshake error to network error code.
+int MapNSSHandshakeError(PRErrorCode err);
+
+} // namespace net
+
+#endif // NET_SOCKET_NSS_SSL_UTIL_H_
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 96280b6..d88399d 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -15,7 +15,6 @@
#include "net/base/address_family.h"
#include "net/base/auth.h"
#include "net/base/host_resolver_proc.h"
-#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_info.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
@@ -403,7 +402,7 @@ int DeterministicMockTCPClientSocket::Read(
return CompleteRead();
}
-void DeterministicMockTCPClientSocket::CompleteWrite(){
+void DeterministicMockTCPClientSocket::CompleteWrite() {
was_used_to_convey_data_ = true;
write_pending_ = false;
write_callback_->Run(write_result_);
@@ -532,18 +531,6 @@ void MockSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
ssl_info->Reset();
}
-void MockSSLClientSocket::GetSSLCertRequestInfo(
- net::SSLCertRequestInfo* cert_request_info) {
- DCHECK(cert_request_info);
- if (data_->cert_request_info) {
- cert_request_info->host_and_port =
- data_->cert_request_info->host_and_port;
- cert_request_info->client_certs = data_->cert_request_info->client_certs;
- } else {
- cert_request_info->Reset();
- }
-}
-
SSLClientSocket::NextProtoStatus MockSSLClientSocket::GetNextProto(
std::string* proto) {
*proto = data_->next_proto;
@@ -1029,6 +1016,7 @@ SSLClientSocket* MockClientSocketFactory::CreateSSLClientSocket(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
MockSSLClientSocket* socket =
new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
@@ -1079,6 +1067,7 @@ SSLClientSocket* DeterministicMockClientSocketFactory::CreateSSLClientSocket(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
MockSSLClientSocket* socket =
new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 38b0054..73dd07c 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -245,14 +245,12 @@ struct SSLSocketDataProvider {
SSLSocketDataProvider(bool async, int result)
: connect(async, result),
next_proto_status(SSLClientSocket::kNextProtoUnsupported),
- was_npn_negotiated(false),
- cert_request_info(NULL) { }
+ was_npn_negotiated(false) { }
MockConnect connect;
SSLClientSocket::NextProtoStatus next_proto_status;
std::string next_proto;
bool was_npn_negotiated;
- net::SSLCertRequestInfo* cert_request_info;
};
// A DataProvider where the client must write a request before the reads (e.g.
@@ -539,6 +537,7 @@ class MockClientSocketFactory : public ClientSocketFactory {
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker);
SocketDataProviderArray<SocketDataProvider>& mock_data() {
return mock_data_;
@@ -715,8 +714,6 @@ class MockSSLClientSocket : public MockClientSocket {
// SSLClientSocket methods:
virtual void GetSSLInfo(net::SSLInfo* ssl_info);
- virtual void GetSSLCertRequestInfo(
- net::SSLCertRequestInfo* cert_request_info);
virtual NextProtoStatus GetNextProto(std::string* proto);
virtual bool was_npn_negotiated() const;
virtual bool set_was_npn_negotiated(bool negotiated);
@@ -886,6 +883,7 @@ class DeterministicMockClientSocketFactory : public ClientSocketFactory {
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker);
SocketDataProviderArray<DeterministicSocketData>& mock_data() {
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc
index c6600a3..b2c5df9 100644
--- a/net/socket/socks5_client_socket.cc
+++ b/net/socket/socks5_client_socket.cc
@@ -113,6 +113,10 @@ bool SOCKS5ClientSocket::IsConnectedAndIdle() const {
return completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
}
+const BoundNetLog& SOCKS5ClientSocket::NetLog() const {
+ return net_log_;
+}
+
void SOCKS5ClientSocket::SetSubresourceSpeculation() {
if (transport_.get() && transport_->socket()) {
transport_->socket()->SetSubresourceSpeculation();
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h
index 36facda..75c8fc5 100644
--- a/net/socket/socks5_client_socket.h
+++ b/net/socket/socks5_client_socket.h
@@ -59,7 +59,7 @@ class SOCKS5ClientSocket : public ClientSocket {
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
- virtual const BoundNetLog& NetLog() const { return net_log_; }
+ virtual const BoundNetLog& NetLog() const;
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc
index 2152c86..5458411 100644
--- a/net/socket/socks5_client_socket_unittest.cc
+++ b/net/socket/socks5_client_socket_unittest.cc
@@ -131,14 +131,19 @@ TEST_F(SOCKS5ClientSocketTest, CompleteHandshake) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(user_sock_->IsConnected());
- EXPECT_TRUE(LogContainsBeginEvent(net_log_.entries(), 0,
+
+ net::CapturingNetLog::EntryList net_log_entries;
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
NetLog::TYPE_SOCKS5_CONNECT));
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
- EXPECT_TRUE(LogContainsEndEvent(net_log_.entries(), -1,
+
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
NetLog::TYPE_SOCKS5_CONNECT));
scoped_refptr<IOBuffer> buffer(new IOBuffer(payload_write.size()));
@@ -248,12 +253,18 @@ TEST_F(SOCKS5ClientSocketTest, PartialReadWrites) {
hostname, 80, &net_log_));
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_TRUE(LogContainsBeginEvent(net_log_.entries(), 0,
+
+ net::CapturingNetLog::EntryList net_log_entries;
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
NetLog::TYPE_SOCKS5_CONNECT));
+
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
- EXPECT_TRUE(LogContainsEndEvent(net_log_.entries(), -1,
+
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
NetLog::TYPE_SOCKS5_CONNECT));
}
@@ -273,12 +284,16 @@ TEST_F(SOCKS5ClientSocketTest, PartialReadWrites) {
hostname, 80, &net_log_));
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_TRUE(LogContainsBeginEvent(net_log_.entries(), 0,
+
+ net::CapturingNetLog::EntryList net_log_entries;
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
NetLog::TYPE_SOCKS5_CONNECT));
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
- EXPECT_TRUE(LogContainsEndEvent(net_log_.entries(), -1,
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
NetLog::TYPE_SOCKS5_CONNECT));
}
@@ -299,12 +314,15 @@ TEST_F(SOCKS5ClientSocketTest, PartialReadWrites) {
hostname, 80, &net_log_));
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_TRUE(LogContainsBeginEvent(net_log_.entries(), 0,
+ net::CapturingNetLog::EntryList net_log_entries;
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
NetLog::TYPE_SOCKS5_CONNECT));
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
- EXPECT_TRUE(LogContainsEndEvent(net_log_.entries(), -1,
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
NetLog::TYPE_SOCKS5_CONNECT));
}
@@ -327,12 +345,15 @@ TEST_F(SOCKS5ClientSocketTest, PartialReadWrites) {
hostname, 80, &net_log_));
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_TRUE(LogContainsBeginEvent(net_log_.entries(), 0,
+ net::CapturingNetLog::EntryList net_log_entries;
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
NetLog::TYPE_SOCKS5_CONNECT));
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
- EXPECT_TRUE(LogContainsEndEvent(net_log_.entries(), -1,
+ net_log_.GetEntries(&net_log_entries);
+ EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
NetLog::TYPE_SOCKS5_CONNECT));
}
}
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index fe3c015..47c654e 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -147,6 +147,10 @@ bool SOCKSClientSocket::IsConnectedAndIdle() const {
return completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
}
+const BoundNetLog& SOCKSClientSocket::NetLog() const {
+ return net_log_;
+}
+
void SOCKSClientSocket::SetSubresourceSpeculation() {
if (transport_.get() && transport_->socket()) {
transport_->socket()->SetSubresourceSpeculation();
diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h
index 653694e..a8fd04c 100644
--- a/net/socket/socks_client_socket.h
+++ b/net/socket/socks_client_socket.h
@@ -56,7 +56,7 @@ class SOCKSClientSocket : public ClientSocket {
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
- virtual const BoundNetLog& NetLog() const { return net_log_; }
+ virtual const BoundNetLog& NetLog() const;
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
diff --git a/net/socket/socks_client_socket_pool.cc b/net/socket/socks_client_socket_pool.cc
index 5b419ba..f7f75b1 100644
--- a/net/socket/socks_client_socket_pool.cc
+++ b/net/socket/socks_client_socket_pool.cc
@@ -247,6 +247,10 @@ void SOCKSClientSocketPool::CloseIdleSockets() {
base_.CloseIdleSockets();
}
+int SOCKSClientSocketPool::IdleSocketCount() const {
+ return base_.idle_socket_count();
+}
+
int SOCKSClientSocketPool::IdleSocketCountInGroup(
const std::string& group_name) const {
return base_.IdleSocketCountInGroup(group_name);
@@ -272,4 +276,12 @@ DictionaryValue* SOCKSClientSocketPool::GetInfoAsValue(
return dict;
}
+base::TimeDelta SOCKSClientSocketPool::ConnectionTimeout() const {
+ return base_.ConnectionTimeout();
+}
+
+ClientSocketPoolHistograms* SOCKSClientSocketPool::histograms() const {
+ return base_.histograms();
+};
+
} // namespace net
diff --git a/net/socket/socks_client_socket_pool.h b/net/socket/socks_client_socket_pool.h
index 35b228e..fd19820 100644
--- a/net/socket/socks_client_socket_pool.h
+++ b/net/socket/socks_client_socket_pool.h
@@ -144,9 +144,7 @@ class SOCKSClientSocketPool : public ClientSocketPool {
virtual void CloseIdleSockets();
- virtual int IdleSocketCount() const {
- return base_.idle_socket_count();
- }
+ virtual int IdleSocketCount() const;
virtual int IdleSocketCountInGroup(const std::string& group_name) const;
@@ -157,13 +155,9 @@ class SOCKSClientSocketPool : public ClientSocketPool {
const std::string& type,
bool include_nested_pools) const;
- virtual base::TimeDelta ConnectionTimeout() const {
- return base_.ConnectionTimeout();
- }
+ virtual base::TimeDelta ConnectionTimeout() const;
- virtual ClientSocketPoolHistograms* histograms() const {
- return base_.histograms();
- };
+ virtual ClientSocketPoolHistograms* histograms() const;
private:
typedef ClientSocketPoolBase<SOCKSSocketParams> PoolBase;
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index 11a88ae..aa5338a 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -142,16 +142,20 @@ TEST_F(SOCKSClientSocketTest, CompleteHandshake) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(
- LogContainsBeginEvent(log.entries(), 0, NetLog::TYPE_SOCKS_CONNECT));
+ LogContainsBeginEvent(entries, 0, NetLog::TYPE_SOCKS_CONNECT));
EXPECT_FALSE(user_sock_->IsConnected());
- rv = callback_.WaitForResult();
+ rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
EXPECT_EQ(SOCKSClientSocket::kSOCKS4, user_sock_->socks_version_);
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
+ entries, -1, NetLog::TYPE_SOCKS_CONNECT));
scoped_refptr<IOBuffer> buffer(new IOBuffer(payload_write.size()));
memcpy(buffer->data(), payload_write.data(), payload_write.size());
@@ -208,14 +212,19 @@ TEST_F(SOCKSClientSocketTest, HandshakeFailures) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKS_CONNECT));
+ entries, 0, NetLog::TYPE_SOCKS_CONNECT));
+
rv = callback_.WaitForResult();
EXPECT_EQ(tests[i].fail_code, rv);
EXPECT_FALSE(user_sock_->IsConnected());
EXPECT_TRUE(tcp_sock_->IsConnected());
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
+ entries, -1, NetLog::TYPE_SOCKS_CONNECT));
}
}
@@ -240,13 +249,17 @@ TEST_F(SOCKSClientSocketTest, PartialServerReads) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKS_CONNECT));
+ entries, 0, NetLog::TYPE_SOCKS_CONNECT));
+
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
+ entries, -1, NetLog::TYPE_SOCKS_CONNECT));
}
// Tests scenario when the client sends the handshake request in
@@ -274,13 +287,17 @@ TEST_F(SOCKSClientSocketTest, PartialClientWrites) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKS_CONNECT));
+ entries, 0, NetLog::TYPE_SOCKS_CONNECT));
+
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
+ entries, -1, NetLog::TYPE_SOCKS_CONNECT));
}
// Tests the case when the server sends a smaller sized handshake data
@@ -302,13 +319,17 @@ TEST_F(SOCKSClientSocketTest, FailedSocketRead) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKS_CONNECT));
+ entries, 0, NetLog::TYPE_SOCKS_CONNECT));
+
rv = callback_.WaitForResult();
EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
EXPECT_FALSE(user_sock_->IsConnected());
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
+ entries, -1, NetLog::TYPE_SOCKS_CONNECT));
}
// Tries to connect to an unknown DNS and on failure should revert to SOCKS4A.
@@ -335,14 +356,18 @@ TEST_F(SOCKSClientSocketTest, SOCKS4AFailedDNS) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKS_CONNECT));
+ entries, 0, NetLog::TYPE_SOCKS_CONNECT));
+
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
EXPECT_EQ(SOCKSClientSocket::kSOCKS4a, user_sock_->socks_version_);
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
+ entries, -1, NetLog::TYPE_SOCKS_CONNECT));
}
// Tries to connect to a domain that resolves to IPv6.
@@ -371,14 +396,18 @@ TEST_F(SOCKSClientSocketTest, SOCKS4AIfDomainInIPv6) {
int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsBeginEvent(
- log.entries(), 0, NetLog::TYPE_SOCKS_CONNECT));
+ entries, 0, NetLog::TYPE_SOCKS_CONNECT));
+
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(user_sock_->IsConnected());
EXPECT_EQ(SOCKSClientSocket::kSOCKS4a, user_sock_->socks_version_);
+ log.GetEntries(&entries);
EXPECT_TRUE(LogContainsEndEvent(
- log.entries(), -1, NetLog::TYPE_SOCKS_CONNECT));
+ entries, -1, NetLog::TYPE_SOCKS_CONNECT));
}
// Calls Disconnect() while a host resolve is in progress. The outstanding host
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc
new file mode 100644
index 0000000..5635ad5
--- /dev/null
+++ b/net/socket/ssl_client_socket.cc
@@ -0,0 +1,62 @@
+// 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/ssl_client_socket.h"
+
+namespace net {
+
+SSLClientSocket::SSLClientSocket()
+ : was_npn_negotiated_(false),
+ was_spdy_negotiated_(false) {
+}
+
+SSLClientSocket::NextProto SSLClientSocket::NextProtoFromString(
+ const std::string& proto_string) {
+ if (proto_string == "http1.1" || proto_string == "http/1.1") {
+ return kProtoHTTP11;
+ } else if (proto_string == "spdy/1") {
+ return kProtoSPDY1;
+ } else if (proto_string == "spdy/2") {
+ return kProtoSPDY2;
+ } else {
+ return kProtoUnknown;
+ }
+}
+
+bool SSLClientSocket::IgnoreCertError(int error, int load_flags) {
+ if (error == OK || load_flags & LOAD_IGNORE_ALL_CERT_ERRORS)
+ return true;
+
+ if (error == ERR_CERT_COMMON_NAME_INVALID &&
+ (load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID))
+ return true;
+
+ if (error == ERR_CERT_DATE_INVALID &&
+ (load_flags & LOAD_IGNORE_CERT_DATE_INVALID))
+ return true;
+
+ if (error == ERR_CERT_AUTHORITY_INVALID &&
+ (load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID))
+ return true;
+
+ return false;
+}
+
+bool SSLClientSocket::was_npn_negotiated() const {
+ return was_npn_negotiated_;
+}
+
+bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) {
+ return was_npn_negotiated_ = negotiated;
+}
+
+bool SSLClientSocket::was_spdy_negotiated() const {
+ return was_spdy_negotiated_;
+}
+
+bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) {
+ return was_spdy_negotiated_ = negotiated;
+}
+
+} // namespace net
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index c3eb0da..0778e85 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -44,12 +44,14 @@ class DNSSECProvider {
//
class SSLClientSocket : public ClientSocket {
public:
- SSLClientSocket() : was_npn_negotiated_(false), was_spdy_negotiated_(false) {
- }
+ SSLClientSocket();
+
// Next Protocol Negotiation (NPN) allows a TLS client and server to come to
// an agreement about the application level protocol to speak over a
// connection.
enum NextProtoStatus {
+ // WARNING: These values are serialised to disk. Don't change them.
+
kNextProtoUnsupported = 0, // The server doesn't support NPN.
kNextProtoNegotiated = 1, // We agreed on a protocol.
kNextProtoNoOverlap = 2, // No protocols in common. We requested
@@ -84,52 +86,19 @@ class SSLClientSocket : public ClientSocket {
// supported list.
virtual NextProtoStatus GetNextProto(std::string* proto) = 0;
- static NextProto NextProtoFromString(const std::string& proto_string) {
- if (proto_string == "http1.1" || proto_string == "http/1.1") {
- return kProtoHTTP11;
- } else if (proto_string == "spdy/1") {
- return kProtoSPDY1;
- } else if (proto_string == "spdy/2") {
- return kProtoSPDY2;
- } else {
- return kProtoUnknown;
- }
- }
-
- static bool IgnoreCertError(int error, int load_flags) {
- if (error == OK || load_flags & LOAD_IGNORE_ALL_CERT_ERRORS)
- return true;
-
- if (error == ERR_CERT_COMMON_NAME_INVALID &&
- (load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID))
- return true;
- if(error == ERR_CERT_DATE_INVALID &&
- (load_flags & LOAD_IGNORE_CERT_DATE_INVALID))
- return true;
- if(error == ERR_CERT_AUTHORITY_INVALID &&
- (load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID))
- return true;
-
- return false;
- }
-
- virtual bool was_npn_negotiated() const {
- return was_npn_negotiated_;
- }
-
- virtual bool set_was_npn_negotiated(bool negotiated) {
- return was_npn_negotiated_ = negotiated;
- }
+ static NextProto NextProtoFromString(const std::string& proto_string);
+
+ static bool IgnoreCertError(int error, int load_flags);
+
+ virtual bool was_npn_negotiated() const;
+
+ virtual bool set_was_npn_negotiated(bool negotiated);
virtual void UseDNSSEC(DNSSECProvider*) { }
- virtual bool was_spdy_negotiated() const {
- return was_spdy_negotiated_;
- }
+ virtual bool was_spdy_negotiated() const;
- virtual bool set_was_spdy_negotiated(bool negotiated) {
- return was_spdy_negotiated_ = negotiated;
- }
+ virtual bool set_was_spdy_negotiated(bool negotiated);
private:
// True if NPN was responded to, independent of selecting SPDY or HTTP.
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index 8b45592..e0753b9 100644
--- a/net/socket/ssl_client_socket_mac.cc
+++ b/net/socket/ssl_client_socket_mac.cc
@@ -13,9 +13,7 @@
#include "base/lazy_instance.h"
#include "base/mac/scoped_cftyperef.h"
-#include "base/singleton.h"
#include "base/string_util.h"
-#include "base/sys_info.h"
#include "net/base/address_list.h"
#include "net/base/cert_verifier.h"
#include "net/base/io_buffer.h"
@@ -142,27 +140,6 @@ enum {
};
#endif
-// On OS X 10.5.x, SSLHandshake() is broken with respect to renegotiation
-// handshakes, and the only way to advance the handshake state machine is
-// to use SSLRead(), which transparently re-handshakes and then reads
-// application data. Using SSLRead() to pump the handshake, rather than
-// SSLHandshake(), is not presently implemented, so on 10.5.x, SSL
-// renegotiation is disabled entirely. On 10.6.x, SSLHandshake() behaves as
-// expected/documented, so renegotiation is supported.
-struct RenegotiationBroken {
- RenegotiationBroken() : broken(false) {
- int32 major, minor, bugfix;
- base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
- if (major < 10 || (major == 10 && minor < 6))
- broken = true;
- }
-
- bool broken;
-};
-
-base::LazyInstance<RenegotiationBroken> g_renegotiation_broken(
- base::LINKER_INITIALIZED);
-
// For an explanation of the Mac OS X error codes, please refer to:
// http://developer.apple.com/mac/library/documentation/Security/Reference/secureTransportRef/Reference/reference.html
int NetErrorFromOSStatus(OSStatus status) {
@@ -498,7 +475,7 @@ class EnabledCipherSuites {
const std::vector<SSLCipherSuite>& ciphers() const { return ciphers_; }
private:
- friend struct DefaultSingletonTraits<EnabledCipherSuites>;
+ friend struct base::DefaultLazyInstanceTraits<EnabledCipherSuites>;
EnabledCipherSuites();
~EnabledCipherSuites() {}
@@ -507,6 +484,9 @@ class EnabledCipherSuites {
DISALLOW_COPY_AND_ASSIGN(EnabledCipherSuites);
};
+static base::LazyInstance<EnabledCipherSuites> g_enabled_cipher_suites(
+ base::LINKER_INITIALIZED);
+
EnabledCipherSuites::EnabledCipherSuites() {
SSLContextRef ssl_context;
OSStatus status = SSLNewContext(false, &ssl_context);
@@ -540,7 +520,8 @@ EnabledCipherSuites::EnabledCipherSuites() {
SSLClientSocketMac::SSLClientSocketMac(ClientSocketHandle* transport_socket,
const HostPortPair& host_and_port,
- const SSLConfig& ssl_config)
+ const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier)
: handshake_io_callback_(this, &SSLClientSocketMac::OnHandshakeIOComplete),
transport_read_callback_(this,
&SSLClientSocketMac::OnTransportReadComplete),
@@ -555,6 +536,7 @@ SSLClientSocketMac::SSLClientSocketMac(ClientSocketHandle* transport_socket,
user_read_buf_len_(0),
user_write_buf_len_(0),
next_handshake_state_(STATE_NONE),
+ cert_verifier_(cert_verifier),
renegotiating_(false),
client_cert_requested_(false),
ssl_context_(NULL),
@@ -800,7 +782,7 @@ int SSLClientSocketMac::InitializeSSLContext() {
status = SSLSetProtocolVersionEnabled(ssl_context_,
kSSLProtocol2,
- ssl_config_.ssl2_enabled);
+ false);
if (status)
return NetErrorFromOSStatus(status);
@@ -817,7 +799,7 @@ int SSLClientSocketMac::InitializeSSLContext() {
return NetErrorFromOSStatus(status);
std::vector<SSLCipherSuite> enabled_ciphers =
- Singleton<EnabledCipherSuites>::get()->ciphers();
+ g_enabled_cipher_suites.Get().ciphers();
CipherSuiteIsDisabledFunctor is_disabled_cipher(
ssl_config_.disabled_cipher_suites);
@@ -1094,7 +1076,7 @@ int SSLClientSocketMac::DoVerifyCert() {
flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
if (ssl_config_.verify_ev_cert)
flags |= X509Certificate::VERIFY_EV_CERT;
- verifier_.reset(new CertVerifier);
+ verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
&server_cert_verify_result_,
&handshake_io_callback_);
@@ -1145,9 +1127,6 @@ int SSLClientSocketMac::DoPayloadRead() {
OSStatus status = SSLRead(ssl_context_, user_read_buf_->data(),
user_read_buf_len_, &processed);
if (status == errSSLWouldBlock && renegotiating_) {
- if (g_renegotiation_broken.Get().broken)
- return ERR_SSL_RENEGOTIATION_REQUESTED;
-
CHECK_EQ(static_cast<size_t>(0), processed);
next_handshake_state_ = STATE_HANDSHAKE;
return DoHandshakeLoop(OK);
diff --git a/net/socket/ssl_client_socket_mac.h b/net/socket/ssl_client_socket_mac.h
index 1e8d888..0a43e2f 100644
--- a/net/socket/ssl_client_socket_mac.h
+++ b/net/socket/ssl_client_socket_mac.h
@@ -23,6 +23,7 @@ namespace net {
class CertVerifier;
class ClientSocketHandle;
+class SingleRequestCertVerifier;
// An SSL client socket implemented with Secure Transport.
class SSLClientSocketMac : public SSLClientSocket {
@@ -35,7 +36,8 @@ class SSLClientSocketMac : public SSLClientSocket {
// the SSL settings.
SSLClientSocketMac(ClientSocketHandle* transport_socket,
const HostPortPair& host_and_port,
- const SSLConfig& ssl_config);
+ const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier);
~SSLClientSocketMac();
// SSLClientSocket methods:
@@ -141,7 +143,8 @@ class SSLClientSocketMac : public SSLClientSocket {
State next_handshake_state_;
scoped_refptr<X509Certificate> server_cert_;
- scoped_ptr<CertVerifier> verifier_;
+ CertVerifier* const cert_verifier_;
+ scoped_ptr<SingleRequestCertVerifier> verifier_;
CertVerifyResult server_cert_verify_result_;
// The initial handshake has already completed, and the current handshake
diff --git a/net/socket/ssl_client_socket_mac_factory.cc b/net/socket/ssl_client_socket_mac_factory.cc
index bf732e6..211e2a4 100644
--- a/net/socket/ssl_client_socket_mac_factory.cc
+++ b/net/socket/ssl_client_socket_mac_factory.cc
@@ -14,9 +14,11 @@ SSLClientSocket* SSLClientSocketMacFactory(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
delete ssl_host_info;
- return new SSLClientSocketMac(transport_socket, host_and_port, ssl_config);
+ return new SSLClientSocketMac(transport_socket, host_and_port, ssl_config,
+ cert_verifier);
}
} // namespace net
diff --git a/net/socket/ssl_client_socket_mac_factory.h b/net/socket/ssl_client_socket_mac_factory.h
index 5539136..ebda9c3 100644
--- a/net/socket/ssl_client_socket_mac_factory.h
+++ b/net/socket/ssl_client_socket_mac_factory.h
@@ -19,6 +19,7 @@ SSLClientSocket* SSLClientSocketMacFactory(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker);
} // namespace net
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 8a9d336..333fe67 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -65,7 +65,6 @@
#include "base/metrics/histogram.h"
#include "base/logging.h"
#include "base/nss_util.h"
-#include "base/singleton.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
@@ -88,6 +87,7 @@
#include "net/ocsp/nss_ocsp.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/dns_cert_provenance_checker.h"
+#include "net/socket/nss_ssl_util.h"
#include "net/socket/ssl_error_params.h"
#include "net/socket/ssl_host_info.h"
@@ -139,180 +139,6 @@ namespace net {
namespace {
-class NSSSSLInitSingleton {
- public:
- NSSSSLInitSingleton() {
- base::EnsureNSSInit();
-
- NSS_SetDomesticPolicy();
-
-#if defined(USE_SYSTEM_SSL)
- // Use late binding to avoid scary but benign warning
- // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
- // consider re-linking"
- // TODO(wtc): Use the new SSL_GetImplementedCiphers and
- // SSL_GetNumImplementedCiphers functions when we require NSS 3.12.6.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=496993.
- const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
- dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
- if (pSSL_ImplementedCiphers == NULL) {
- NOTREACHED() << "Can't get list of supported ciphers";
- return;
- }
-#else
-#define pSSL_ImplementedCiphers SSL_ImplementedCiphers
-#endif
-
- // Explicitly enable exactly those ciphers with keys of at least 80 bits
- for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
- SSLCipherSuiteInfo info;
- if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
- sizeof(info)) == SECSuccess) {
- SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
- (info.effectiveKeyBits >= 80));
- }
- }
-
- // Enable SSL.
- SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
-
- // All other SSL options are set per-session by SSLClientSocket.
- }
-
- ~NSSSSLInitSingleton() {
- // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
- SSL_ClearSessionCache();
- }
-};
-
-// Initialize the NSS SSL library if it isn't already initialized. This must
-// be called before any other NSS SSL functions. This function is
-// 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();
-}
-
-// The default error mapping function.
-// Maps an NSPR error code to a network error code.
-int MapNSPRError(PRErrorCode err) {
- // TODO(port): fill this out as we learn what's important
- switch (err) {
- case PR_WOULD_BLOCK_ERROR:
- return ERR_IO_PENDING;
- case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect.
- case PR_NO_ACCESS_RIGHTS_ERROR:
- return ERR_ACCESS_DENIED;
- case PR_IO_TIMEOUT_ERROR:
- return ERR_TIMED_OUT;
- case PR_CONNECT_RESET_ERROR:
- return ERR_CONNECTION_RESET;
- case PR_CONNECT_ABORTED_ERROR:
- return ERR_CONNECTION_ABORTED;
- case PR_CONNECT_REFUSED_ERROR:
- return ERR_CONNECTION_REFUSED;
- case PR_HOST_UNREACHABLE_ERROR:
- case PR_NETWORK_UNREACHABLE_ERROR:
- return ERR_ADDRESS_UNREACHABLE;
- case PR_ADDRESS_NOT_AVAILABLE_ERROR:
- return ERR_ADDRESS_INVALID;
- case PR_INVALID_ARGUMENT_ERROR:
- 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;
-
- case SSL_ERROR_SSL_DISABLED:
- return ERR_NO_SSL_VERSIONS_ENABLED;
- case SSL_ERROR_NO_CYPHER_OVERLAP:
- case SSL_ERROR_UNSUPPORTED_VERSION:
- return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
- case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
- case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
- case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
- return ERR_SSL_PROTOCOL_ERROR;
- case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT:
- return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
- case SSL_ERROR_BAD_MAC_ALERT:
- return ERR_SSL_BAD_RECORD_MAC_ALERT;
- case SSL_ERROR_UNSAFE_NEGOTIATION:
- return ERR_SSL_UNSAFE_NEGOTIATION;
- case SSL_ERROR_WEAK_SERVER_KEY:
- return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
-
- default: {
- if (IS_SSL_ERROR(err)) {
- LOG(WARNING) << "Unknown SSL error " << err <<
- " mapped to net::ERR_SSL_PROTOCOL_ERROR";
- return ERR_SSL_PROTOCOL_ERROR;
- }
- LOG(WARNING) << "Unknown error " << err <<
- " mapped to net::ERR_FAILED";
- return ERR_FAILED;
- }
- }
-}
-
-// Context-sensitive error mapping functions.
-
-int MapHandshakeError(PRErrorCode err) {
- switch (err) {
- // If the server closed on us, it is a protocol error.
- // Some TLS-intolerant servers do this when we request TLS.
- case PR_END_OF_FILE_ERROR:
- // The handshake may fail because some signature (for example, the
- // signature in the ServerKeyExchange message for an ephemeral
- // Diffie-Hellman cipher suite) is invalid.
- case SEC_ERROR_BAD_SIGNATURE:
- return ERR_SSL_PROTOCOL_ERROR;
- default:
- return MapNSPRError(err);
- }
-}
-
-// Extra parameters to attach to the NetLog when we receive an error in response
-// to a call to an NSS function. Used instead of SSLErrorParams with
-// events of type TYPE_SSL_NSS_ERROR. Automatically looks up last PR error.
-class SSLFailedNSSFunctionParams : public NetLog::EventParameters {
- public:
- // |param| is ignored if it has a length of 0.
- SSLFailedNSSFunctionParams(const std::string& function,
- const std::string& param)
- : function_(function), param_(param), ssl_lib_error_(PR_GetError()) {
- }
-
- virtual Value* ToValue() const {
- DictionaryValue* dict = new DictionaryValue();
- dict->SetString("function", function_);
- if (!param_.empty())
- dict->SetString("param", param_);
- dict->SetInteger("ssl_lib_error", ssl_lib_error_);
- return dict;
- }
-
- private:
- const std::string function_;
- const std::string param_;
- const PRErrorCode ssl_lib_error_;
-};
-
-void LogFailedNSSFunction(const BoundNetLog& net_log,
- const char* function,
- const char* param) {
- net_log.AddEvent(
- NetLog::TYPE_SSL_NSS_ERROR,
- make_scoped_refptr(new SSLFailedNSSFunctionParams(function, param)));
-}
-
#if defined(OS_WIN)
// This callback is intended to be used with CertFindChainInStore. In addition
@@ -405,6 +231,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_ctx)
: ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
this, &SSLClientSocketNSS::BufferSendComplete)),
@@ -427,6 +254,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
server_cert_verify_result_(NULL),
ssl_connection_status_(0),
client_auth_cert_needed_(false),
+ cert_verifier_(cert_verifier),
handshake_callback_called_(false),
completed_handshake_(false),
pseudo_connected_(false),
@@ -476,6 +304,11 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
if (!ssl_host_info_.get())
return;
+ // If the SSLHostInfo hasn't managed to load from disk yet then we can't save
+ // anything.
+ if (ssl_host_info_->WaitForDataReady(NULL) != OK)
+ return;
+
SECStatus rv;
SSLSnapStartResult snap_start_type;
rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
@@ -485,8 +318,6 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
}
net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START,
new NetLogIntegerParameter("type", snap_start_type));
- LOG(ERROR) << "Snap Start: " << snap_start_type << " "
- << host_and_port_.ToString();
if (snap_start_type == SSL_SNAP_START_FULL ||
snap_start_type == SSL_SNAP_START_RESUME) {
// If we did a successful Snap Start then our information was correct and
@@ -504,14 +335,13 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
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);
if (hello_data_len > 0) {
- 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);
} else {
- state->server_hello.clear();
state->npn_valid = false;
}
@@ -526,7 +356,6 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
certs[i]->derCert.len));
}
- LOG(ERROR) << "Setting Snap Start info " << host_and_port_.ToString();
ssl_host_info_->Persist();
}
@@ -694,19 +523,14 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_UNEXPECTED;
}
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, ssl_config_.ssl2_enabled);
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
return ERR_UNEXPECTED;
}
- // SNI is enabled automatically if TLS is enabled -- as long as
- // SSL_V2_COMPATIBLE_HELLO isn't.
- // So don't do V2 compatible hellos unless we're really using SSL2,
- // to avoid errors like
- // "common name `mail.google.com' != requested host name `gmail.com'"
- rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO,
- ssl_config_.ssl2_enabled);
+ // Don't do V2 compatible hellos because they don't support TLS extensions.
+ rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
return ERR_UNEXPECTED;
@@ -743,6 +567,13 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
#error "You need to install NSS-3.12 or later to build chromium"
#endif
+ rv = SSL_OptionSet(nss_fd_, SSL_NO_CACHE,
+ ssl_config_.session_resume_disabled);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_NO_CACHE");
+ return ERR_UNEXPECTED;
+ }
+
#ifdef SSL_ENABLE_DEFLATE
// Some web servers have been found to break if TLS is used *or* if DEFLATE
// is advertised. Thus, if TLS is disabled (probably because we are doing
@@ -919,6 +750,7 @@ void SSLClientSocketNSS::Disconnect() {
completed_handshake_ = false;
pseudo_connected_ = false;
eset_mitm_detected_ = false;
+ start_cert_verification_time_ = base::TimeTicks();
predicted_cert_chain_correct_ = false;
peername_initialized_ = false;
nss_bufs_ = NULL;
@@ -962,6 +794,10 @@ int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const {
return transport_->socket()->GetPeerAddress(address);
}
+const BoundNetLog& SSLClientSocketNSS::NetLog() const {
+ return net_log_;
+}
+
void SSLClientSocketNSS::SetSubresourceSpeculation() {
if (transport_.get() && transport_->socket()) {
transport_->socket()->SetSubresourceSpeculation();
@@ -1365,46 +1201,6 @@ void SSLClientSocketNSS::OnRecvComplete(int result) {
LeaveFunction("");
}
-// Map a Chromium net error code to an NSS error code.
-// See _MD_unix_map_default_error in the NSS source
-// tree for inspiration.
-static PRErrorCode MapErrorToNSS(int result) {
- if (result >=0)
- return result;
-
- switch (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:
- case ERR_TIMED_OUT:
- return PR_IO_TIMEOUT_ERROR;
- case ERR_CONNECTION_RESET:
- return PR_CONNECT_RESET_ERROR;
- case ERR_CONNECTION_ABORTED:
- return PR_CONNECT_ABORTED_ERROR;
- case ERR_CONNECTION_REFUSED:
- return PR_CONNECT_REFUSED_ERROR;
- case ERR_ADDRESS_UNREACHABLE:
- return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR.
- case ERR_ADDRESS_INVALID:
- return PR_ADDRESS_NOT_AVAILABLE_ERROR;
- case ERR_NAME_NOT_RESOLVED:
- return PR_DIRECTORY_LOOKUP_ERROR;
- default:
- LOG(WARNING) << "MapErrorToNSS " << result
- << " mapped to PR_UNKNOWN_ERROR";
- return PR_UNKNOWN_ERROR;
- }
-}
-
// Do network I/O between the given buffer and the given socket.
// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
bool SSLClientSocketNSS::DoTransportIO() {
@@ -1648,7 +1444,8 @@ 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) {
+ 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);
@@ -2192,7 +1989,7 @@ int SSLClientSocketNSS::DoHandshake() {
}
} else {
PRErrorCode prerr = PR_GetError();
- net_error = MapHandshakeError(prerr);
+ net_error = MapNSSHandshakeError(prerr);
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
@@ -2443,6 +2240,7 @@ int SSLClientSocketNSS::DoVerifyCert(int result) {
DCHECK(server_cert_);
GotoState(STATE_VERIFY_CERT_COMPLETE);
+ start_cert_verification_time_ = base::TimeTicks::Now();
if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() &&
predicted_cert_chain_correct_) {
@@ -2452,9 +2250,11 @@ int SSLClientSocketNSS::DoVerifyCert(int result) {
// 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();
+ base::TimeTicks end_time = ssl_host_info_->verification_end_time();
+ if (end_time.is_null())
+ end_time = base::TimeTicks::Now();
UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved",
- now - ssl_host_info_->verification_start_time());
+ end_time - 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 {
@@ -2466,7 +2266,7 @@ int SSLClientSocketNSS::DoVerifyCert(int result) {
flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
if (ssl_config_.verify_ev_cert)
flags |= X509Certificate::VERIFY_EV_CERT;
- verifier_.reset(new CertVerifier);
+ verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
server_cert_verify_result_ = &local_server_cert_verify_result_;
return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
&local_server_cert_verify_result_,
@@ -2478,6 +2278,16 @@ int SSLClientSocketNSS::DoVerifyCert(int result) {
int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
verifier_.reset();
+
+ if (!start_cert_verification_time_.is_null()) {
+ base::TimeDelta verify_time =
+ base::TimeTicks::Now() - start_cert_verification_time_;
+ if (result == OK)
+ UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
+ else
+ UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
+ }
+
// 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
@@ -2568,7 +2378,7 @@ int SSLClientSocketNSS::DoPayloadRead() {
return ERR_IO_PENDING;
}
LeaveFunction("");
- rv = MapNSPRError(prerr);
+ rv = MapNSSError(prerr);
net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
make_scoped_refptr(new SSLErrorParams(rv, prerr)));
return rv;
@@ -2589,7 +2399,7 @@ int SSLClientSocketNSS::DoPayloadWrite() {
return ERR_IO_PENDING;
}
LeaveFunction("");
- rv = MapNSPRError(prerr);
+ rv = MapNSSError(prerr);
net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
make_scoped_refptr(new SSLErrorParams(rv, prerr)));
return rv;
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
index 6f291b3..6389db8 100644
--- a/net/socket/ssl_client_socket_nss.h
+++ b/net/socket/ssl_client_socket_nss.h
@@ -32,6 +32,7 @@ class BoundNetLog;
class CertVerifier;
class ClientSocketHandle;
class DnsCertProvenanceChecker;
+class SingleRequestCertVerifier;
class SSLHostInfo;
class X509Certificate;
@@ -48,6 +49,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dnsrr_resolver);
~SSLClientSocketNSS();
@@ -67,7 +69,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
virtual int GetPeerAddress(AddressList* address) const;
- virtual const BoundNetLog& NetLog() const { return net_log_; }
+ virtual const BoundNetLog& NetLog() const;
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
@@ -197,7 +199,8 @@ class SSLClientSocketNSS : public SSLClientSocket {
std::vector<scoped_refptr<X509Certificate> > client_certs_;
bool client_auth_cert_needed_;
- scoped_ptr<CertVerifier> verifier_;
+ CertVerifier* const cert_verifier_;
+ scoped_ptr<SingleRequestCertVerifier> verifier_;
// True if NSS has called HandshakeCallback.
bool handshake_callback_called_;
@@ -253,6 +256,8 @@ class SSLClientSocketNSS : public SSLClientSocket {
std::string predicted_npn_proto_;
bool predicted_npn_proto_used_;
+ base::TimeTicks start_cert_verification_time_;
+
scoped_ptr<SSLHostInfo> ssl_host_info_;
DnsCertProvenanceChecker* const dns_cert_checker_;
};
diff --git a/net/socket/ssl_client_socket_nss_factory.cc b/net/socket/ssl_client_socket_nss_factory.cc
index e4c01f0..435ddff 100644
--- a/net/socket/ssl_client_socket_nss_factory.cc
+++ b/net/socket/ssl_client_socket_nss_factory.cc
@@ -19,10 +19,11 @@ SSLClientSocket* SSLClientSocketNSSFactory(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
scoped_ptr<SSLHostInfo> shi(ssl_host_info);
return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config,
- shi.release(), dns_cert_checker);
+ shi.release(), cert_verifier, dns_cert_checker);
}
} // namespace net
diff --git a/net/socket/ssl_client_socket_nss_factory.h b/net/socket/ssl_client_socket_nss_factory.h
index 15b05b2..ed5e588 100644
--- a/net/socket/ssl_client_socket_nss_factory.h
+++ b/net/socket/ssl_client_socket_nss_factory.h
@@ -19,6 +19,7 @@ SSLClientSocket* SSLClientSocketNSSFactory(
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker);
} // namespace net
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index f80b21c..8bef0ef 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -19,8 +19,11 @@
#include "base/singleton.h"
#include "net/base/cert_verifier.h"
#include "net/base/net_errors.h"
+#include "net/base/openssl_private_key_store.h"
+#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
#include "net/base/ssl_info.h"
+#include "net/socket/ssl_error_params.h"
namespace net {
@@ -39,7 +42,140 @@ const size_t kMaxRecvBufferSize = 4096;
const int kSessionCacheTimeoutSeconds = 60 * 60;
const size_t kSessionCacheMaxEntires = 1024;
-int MapOpenSSLError(int err) {
+// This method doesn't seemed to have made it into the OpenSSL headers.
+unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; }
+
+// Used for encoding the |connection_status| field of an SSLInfo object.
+int EncodeSSLConnectionStatus(int cipher_suite,
+ int compression,
+ int version) {
+ return ((cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) <<
+ SSL_CONNECTION_CIPHERSUITE_SHIFT) |
+ ((compression & SSL_CONNECTION_COMPRESSION_MASK) <<
+ SSL_CONNECTION_COMPRESSION_SHIFT) |
+ ((version & SSL_CONNECTION_VERSION_MASK) <<
+ SSL_CONNECTION_VERSION_SHIFT);
+}
+
+// Returns the net SSL version number (see ssl_connection_status_flags.h) for
+// this SSL connection.
+int GetNetSSLVersion(SSL* ssl) {
+ switch (SSL_version(ssl)) {
+ case SSL2_VERSION:
+ return SSL_CONNECTION_VERSION_SSL2;
+ case SSL3_VERSION:
+ return SSL_CONNECTION_VERSION_SSL3;
+ case TLS1_VERSION:
+ return SSL_CONNECTION_VERSION_TLS1;
+ case 0x0302:
+ return SSL_CONNECTION_VERSION_TLS1_1;
+ case 0x0303:
+ return SSL_CONNECTION_VERSION_TLS1_2;
+ default:
+ return SSL_CONNECTION_VERSION_UNKNOWN;
+ }
+}
+
+int MapOpenSSLErrorSSL() {
+ // Walk down the error stack to find the SSLerr generated reason.
+ unsigned long error_code;
+ do {
+ error_code = ERR_get_error();
+ if (error_code == 0)
+ return ERR_SSL_PROTOCOL_ERROR;
+ } while (ERR_GET_LIB(error_code) != ERR_LIB_SSL);
+
+ DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code)
+ << ", name: " << ERR_error_string(error_code, NULL);
+ switch (ERR_GET_REASON(error_code)) {
+ case SSL_R_READ_TIMEOUT_EXPIRED:
+ return ERR_TIMED_OUT;
+ case SSL_R_BAD_RESPONSE_ARGUMENT:
+ return ERR_INVALID_ARGUMENT;
+ case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
+ case SSL_R_UNKNOWN_CIPHER_TYPE:
+ case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
+ case SSL_R_UNKNOWN_PKEY_TYPE:
+ case SSL_R_UNKNOWN_REMOTE_ERROR_TYPE:
+ case SSL_R_UNKNOWN_SSL_VERSION:
+ return ERR_NOT_IMPLEMENTED;
+ case SSL_R_UNSUPPORTED_SSL_VERSION:
+ case SSL_R_NO_CIPHER_MATCH:
+ case SSL_R_NO_SHARED_CIPHER:
+ case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:
+ case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
+ return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
+ case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
+ case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:
+ case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
+ case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
+ case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
+ case SSL_R_TLSV1_ALERT_ACCESS_DENIED:
+ case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
+ return ERR_BAD_SSL_CLIENT_AUTH_CERT;
+ case SSL_R_BAD_DECOMPRESSION:
+ case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:
+ return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
+ case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:
+ return ERR_SSL_BAD_RECORD_MAC_ALERT;
+ case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:
+ return ERR_SSL_UNSAFE_NEGOTIATION;
+ case SSL_R_WRONG_NUMBER_OF_KEY_BITS:
+ return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
+ // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is
+ // received (see http://crbug.com/42538), and also if all the protocol
+ // versions supported by the server were disabled in this socket instance.
+ // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets
+ // in the former scenario.
+ case SSL_R_UNKNOWN_PROTOCOL:
+ case SSL_R_SSL_HANDSHAKE_FAILURE:
+ case SSL_R_DECRYPTION_FAILED:
+ case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
+ case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:
+ case SSL_R_DIGEST_CHECK_FAILED:
+ case SSL_R_DUPLICATE_COMPRESSION_ID:
+ case SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER:
+ case SSL_R_ENCRYPTED_LENGTH_TOO_LONG:
+ case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:
+ case SSL_R_EXCESSIVE_MESSAGE_SIZE:
+ case SSL_R_EXTRA_DATA_IN_MESSAGE:
+ case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
+ case SSL_R_ILLEGAL_PADDING:
+ case SSL_R_INVALID_CHALLENGE_LENGTH:
+ case SSL_R_INVALID_COMMAND:
+ case SSL_R_INVALID_PURPOSE:
+ case SSL_R_INVALID_STATUS_RESPONSE:
+ case SSL_R_INVALID_TICKET_KEYS_LENGTH:
+ case SSL_R_KEY_ARG_TOO_LONG:
+ case SSL_R_READ_WRONG_PACKET_TYPE:
+ case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
+ // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
+ // server after receiving ClientHello if there's no common supported cipher.
+ // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
+ // to match the NSS implementation. See also http://goo.gl/oMtZW
+ case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
+ case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
+ case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
+ case SSL_R_TLSV1_ALERT_DECODE_ERROR:
+ case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
+ case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:
+ case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:
+ case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:
+ case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:
+ case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:
+ case SSL_R_TLSV1_ALERT_USER_CANCELLED:
+ return ERR_SSL_PROTOCOL_ERROR;
+ default:
+ LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
+ return ERR_FAILED;
+ }
+}
+
+// Converts an OpenSSL error code into a net error code, walking the OpenSSL
+// error stack if needed. Note that |tracer| is not currently used in the
+// implementation, but is passed in anyway as this ensures the caller will clear
+// any residual codes left on the error stack.
+int MapOpenSSLError(int err, const base::OpenSSLErrStackTracer& tracer) {
switch (err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
@@ -47,6 +183,8 @@ int MapOpenSSLError(int err) {
case SSL_ERROR_SYSCALL:
DVLOG(1) << "OpenSSL SYSCALL error, errno " << errno;
return ERR_SSL_PROTOCOL_ERROR;
+ case SSL_ERROR_SSL:
+ return MapOpenSSLErrorSSL();
default:
// TODO(joth): Implement full mapping.
LOG(WARNING) << "Unknown OpenSSL error " << err;
@@ -130,7 +268,7 @@ class SSLSessionCache {
private:
// A pair of maps to allow bi-directional lookups between host:port and an
- // associated seesion.
+ // associated session.
// TODO(joth): When client certificates are implemented we should key the
// cache on the client certificate used in addition to the host-port pair.
typedef std::map<HostPortPair, SSL_SESSION*> HostPortMap;
@@ -146,7 +284,7 @@ class SSLSessionCache {
class SSLContext {
public:
- static SSLContext* Get() { return Singleton<SSLContext>::get(); }
+ static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); }
SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
SSLSessionCache* session_cache() { return &session_cache_; }
@@ -176,7 +314,11 @@ class SSLContext {
SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic);
SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds);
SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires);
+<<<<<<< HEAD
#ifdef ANDROID
+=======
+ SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback);
+>>>>>>> chromium.org at r10.0.621.0
#if defined(OPENSSL_NPN_NEGOTIATED)
// TODO(kristianm): Only select this if ssl_config_.next_proto is not empty.
// It would be better if the callback were not a global setting,
@@ -184,11 +326,14 @@ class SSLContext {
SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback,
NULL);
#endif
+<<<<<<< HEAD
#endif
+=======
+>>>>>>> chromium.org at r10.0.621.0
}
static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
- return Get()->NewSessionCallback(ssl, session);
+ return GetInstance()->NewSessionCallback(ssl, session);
}
int NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
@@ -198,7 +343,7 @@ class SSLContext {
}
static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
- return Get()->RemoveSessionCallback(ctx, session);
+ return GetInstance()->RemoveSessionCallback(ctx, session);
}
void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) {
@@ -206,15 +351,30 @@ class SSLContext {
session_cache_.OnSessionRemoved(session);
}
+<<<<<<< HEAD
#ifdef ANDROID
+=======
+ static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) {
+ SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
+ CHECK(socket);
+ return socket->ClientCertRequestCallback(ssl, x509, pkey);
+ }
+
+>>>>>>> chromium.org at r10.0.621.0
static int SelectNextProtoCallback(SSL* ssl,
unsigned char** out, unsigned char* outlen,
const unsigned char* in,
unsigned int inlen, void* arg) {
+<<<<<<< HEAD
SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl);
return socket->SelectNextProtoCallback(out, outlen, in, inlen);
}
#endif
+=======
+ SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
+ return socket->SelectNextProtoCallback(out, outlen, in, inlen);
+ }
+>>>>>>> chromium.org at r10.0.621.0
// This is the index used with SSL_get_ex_data to retrieve the owner
// SSLClientSocketOpenSSL object from an SSL instance.
@@ -242,7 +402,8 @@ struct SslSetClearMask {
SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
ClientSocketHandle* transport_socket,
const HostPortPair& host_and_port,
- const SSLConfig& ssl_config)
+ const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier)
: ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
this, &SSLClientSocketOpenSSL::BufferSendComplete)),
ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
@@ -254,6 +415,7 @@ SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
user_write_callback_(NULL),
completed_handshake_(false),
client_auth_cert_needed_(false),
+ cert_verifier_(cert_verifier),
ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)),
ssl_(NULL),
@@ -262,9 +424,13 @@ SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
host_and_port_(host_and_port),
ssl_config_(ssl_config),
trying_cached_session_(false),
+<<<<<<< HEAD
#ifdef ANDROID
npn_status_(kNextProtoUnsupported),
#endif
+=======
+ npn_status_(kNextProtoUnsupported),
+>>>>>>> chromium.org at r10.0.621.0
net_log_(transport_socket->socket()->NetLog()) {
}
@@ -276,7 +442,7 @@ bool SSLClientSocketOpenSSL::Init() {
DCHECK(!ssl_);
DCHECK(!transport_bio_);
- SSLContext* context = SSLContext::Get();
+ SSLContext* context = SSLContext::GetInstance();
base::OpenSSLErrStackTracer err_tracer(FROM_HERE);
ssl_ = SSL_new(context->ssl_ctx());
@@ -316,6 +482,23 @@ bool SSLClientSocketOpenSSL::Init() {
SSL_set_options(ssl_, options.set_mask);
SSL_clear_options(ssl_, options.clear_mask);
+<<<<<<< HEAD
+
+ // Same as above, this time for the SSL mode.
+ SslSetClearMask mode;
+
+#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH)
+ mode.ConfigureFlag(SSL_MODE_HANDSHAKE_CUTTHROUGH,
+ ssl_config_.false_start_enabled &&
+ !SSLConfigService::IsKnownFalseStartIncompatibleServer(
+ host_and_port_.host()));
+#endif
+
+#if defined(SSL_MODE_RELEASE_BUFFERS)
+ mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
+#endif
+
+=======
// Same as above, this time for the SSL mode.
SslSetClearMask mode;
@@ -331,15 +514,90 @@ bool SSLClientSocketOpenSSL::Init() {
mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
#endif
+>>>>>>> chromium.org at r10.0.621.0
#if defined(SSL_MODE_SMALL_BUFFERS)
mode.ConfigureFlag(SSL_MODE_SMALL_BUFFERS, true);
#endif
SSL_set_mode(ssl_, mode.set_mask);
SSL_clear_mode(ssl_, mode.clear_mask);
+<<<<<<< HEAD
+=======
+
+ // Removing ciphers by ID from OpenSSL is a bit involved as we must use the
+ // textual name with SSL_set_cipher_list because there is no public API to
+ // directly remove a cipher by ID.
+ STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl_);
+ DCHECK(ciphers);
+ // See SSLConfig::disabled_cipher_suites for description of the suites
+ // disabled by default.
+ std::string command("DEFAULT:!NULL:!aNULL:!IDEA:!FZA");
+ // Walk through all the installed ciphers, seeing if any need to be
+ // appended to the cipher removal |command|.
+ for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
+ const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
+ const uint16 id = SSL_CIPHER_get_id(cipher);
+ // Remove any ciphers with a strength of less than 80 bits. Note the NSS
+ // implementation uses "effective" bits here but OpenSSL does not provide
+ // this detail. This only impacts Triple DES: reports 112 vs. 168 bits,
+ // both of which are greater than 80 anyway.
+ bool disable = SSL_CIPHER_get_bits(cipher, NULL) < 80;
+ if (!disable) {
+ disable = std::find(ssl_config_.disabled_cipher_suites.begin(),
+ ssl_config_.disabled_cipher_suites.end(), id) !=
+ ssl_config_.disabled_cipher_suites.end();
+ }
+ if (disable) {
+ const char* name = SSL_CIPHER_get_name(cipher);
+ DVLOG(3) << "Found cipher to remove: '" << name << "', ID: " << id
+ << " strength: " << SSL_CIPHER_get_bits(cipher, NULL);
+ command.append(":!");
+ command.append(name);
+ }
+ }
+ int rv = SSL_set_cipher_list(ssl_, command.c_str());
+ // If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
+ // This will almost certainly result in the socket failing to complete the
+ // handshake at which point the appropriate error is bubbled up to the client.
+ LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command << "') "
+ "returned " << rv;
+>>>>>>> chromium.org at r10.0.621.0
return true;
}
+int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
+ X509** x509,
+ EVP_PKEY** pkey) {
+ DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
+ DCHECK(ssl == ssl_);
+ DCHECK(*x509 == NULL);
+ DCHECK(*pkey == NULL);
+
+ if (!ssl_config_.send_client_cert) {
+ client_auth_cert_needed_ = true;
+ return -1; // Suspends handshake.
+ }
+
+ // Second pass: a client certificate should have been selected.
+ if (ssl_config_.client_cert) {
+ EVP_PKEY* privkey = OpenSSLPrivateKeyStore::GetInstance()->FetchPrivateKey(
+ X509_PUBKEY_get(X509_get_X509_PUBKEY(
+ ssl_config_.client_cert->os_cert_handle())));
+ if (privkey) {
+ // TODO(joth): (copied from NSS) We should wait for server certificate
+ // verification before sending our credentials. See http://crbug.com/13934
+ *x509 = X509Certificate::DupOSCertHandle(
+ ssl_config_.client_cert->os_cert_handle());
+ *pkey = privkey;
+ return 1;
+ }
+ LOG(WARNING) << "Client cert found without private key";
+ }
+
+ // Send no client certificate.
+ return 0;
+}
+
// SSLClientSocket methods
void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
@@ -353,43 +611,47 @@ void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
CHECK(cipher);
ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
- ssl_info->connection_status |= (cipher->id & SSL_CONNECTION_CIPHERSUITE_MASK)
- << SSL_CONNECTION_CIPHERSUITE_SHIFT;
- DVLOG(2) << SSL_CIPHER_get_name(cipher) << ": cipher ID " << cipher->id
- << " security bits " << ssl_info->security_bits;
-
- // Experimenting suggests the compression object is optional, whereas the
- // cipher (above) is always present.
const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
- if (compression) {
- ssl_info->connection_status |=
- (compression->type & SSL_CONNECTION_COMPRESSION_MASK)
- << SSL_CONNECTION_COMPRESSION_SHIFT;
- DVLOG(2) << SSL_COMP_get_name(compression)
- << ": compression ID " << compression->type;
- }
+
+ ssl_info->connection_status = EncodeSSLConnectionStatus(
+ SSL_CIPHER_get_id(cipher),
+ compression ? compression->type : 0,
+ GetNetSSLVersion(ssl_));
bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
if (!peer_supports_renego_ext)
ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
- UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
- (int)peer_supports_renego_ext, 2);
+ UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
+ implicit_cast<int>(peer_supports_renego_ext), 2);
if (ssl_config_.ssl3_fallback)
ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
+
+ DVLOG(3) << "Encoded connection status: cipher suite = "
+ << SSLConnectionStatusToCipherSuite(ssl_info->connection_status)
+ << " compression = "
+ << SSLConnectionStatusToCompression(ssl_info->connection_status)
+ << " version = "
+ << SSLConnectionStatusToVersion(ssl_info->connection_status);
}
void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
- NOTREACHED();
+ cert_request_info->host_and_port = host_and_port_.ToString();
+ cert_request_info->client_certs = client_certs_;
}
SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
std::string* proto) {
+<<<<<<< HEAD
#ifdef ANDROID
*proto = npn_proto_;
return npn_status_;
#endif
+=======
+ *proto = npn_proto_;
+ return npn_status_;
+>>>>>>> chromium.org at r10.0.621.0
}
void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
@@ -528,19 +790,33 @@ int SSLClientSocketOpenSSL::DoHandshake() {
int net_error = net::OK;
int rv = SSL_do_handshake(ssl_);
- if (rv == 1) {
+ if (client_auth_cert_needed_) {
+ net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
+ // 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
+ // the next handshake. This will cause the server to ask for a client
+ // cert again.
+ if (rv == 1) {
+ // Remove from session cache but don't clear this connection.
+ SSL_SESSION* session = SSL_get_session(ssl_);
+ if (session) {
+ int rv = SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl_), session);
+ LOG_IF(WARNING, !rv) << "Couldn't invalidate SSL session: " << session;
+ }
+ }
+ } else if (rv == 1) {
if (trying_cached_session_ && logging::DEBUG_MODE) {
DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString()
<< " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail");
}
-
// SSL handshake is completed. Let's verify the certificate.
const bool got_cert = !!UpdateServerCert();
DCHECK(got_cert);
GotoState(STATE_VERIFY_CERT);
} else {
int ssl_error = SSL_get_error(ssl_, rv);
- net_error = MapOpenSSLError(ssl_error);
+ net_error = MapOpenSSLError(ssl_error, err_tracer);
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
@@ -549,12 +825,18 @@ int SSLClientSocketOpenSSL::DoHandshake() {
LOG(ERROR) << "handshake failed; returned " << rv
<< ", SSL error code " << ssl_error
<< ", net_error " << net_error;
+ net_log_.AddEvent(
+ NetLog::TYPE_SSL_HANDSHAKE_ERROR,
+ make_scoped_refptr(new SSLErrorParams(net_error, ssl_error)));
}
}
return net_error;
}
+<<<<<<< HEAD
#ifdef ANDROID
+=======
+>>>>>>> chromium.org at r10.0.621.0
int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
unsigned char* outlen,
const unsigned char* in,
@@ -587,10 +869,17 @@ int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
NOTREACHED() << status;
break;
}
+<<<<<<< HEAD
#endif
return SSL_TLSEXT_ERR_OK;
}
#endif
+=======
+ DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
+#endif
+ return SSL_TLSEXT_ERR_OK;
+}
+>>>>>>> chromium.org at r10.0.621.0
int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
DCHECK(server_cert_);
@@ -601,7 +890,7 @@ int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
if (ssl_config_.verify_ev_cert)
flags |= X509Certificate::VERIFY_EV_CERT;
- verifier_.reset(new CertVerifier);
+ verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
&server_cert_verify_result_,
&handshake_io_callback_);
@@ -961,7 +1250,7 @@ int SSLClientSocketOpenSSL::DoPayloadRead() {
return rv;
int err = SSL_get_error(ssl_, rv);
- return MapOpenSSLError(err);
+ return MapOpenSSLError(err, err_tracer);
}
int SSLClientSocketOpenSSL::DoPayloadWrite() {
@@ -972,7 +1261,7 @@ int SSLClientSocketOpenSSL::DoPayloadWrite() {
return rv;
int err = SSL_get_error(ssl_, rv);
- return MapOpenSSLError(err);
+ return MapOpenSSLError(err, err_tracer);
}
-} // namespace net
+} // namespace net
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h
index c8f5d81..72dab75 100644
--- a/net/socket/ssl_client_socket_openssl.h
+++ b/net/socket/ssl_client_socket_openssl.h
@@ -6,6 +6,8 @@
#define NET_SOCKET_SSL_CLIENT_SOCKET_OPENSSL_H_
#pragma once
+#include <string>
+
#include "base/scoped_ptr.h"
#include "net/base/cert_verify_result.h"
#include "net/base/completion_callback.h"
@@ -15,11 +17,14 @@
#include "net/socket/client_socket_handle.h"
typedef struct bio_st BIO;
+typedef struct evp_pkey_st EVP_PKEY;
typedef struct ssl_st SSL;
+typedef struct x509_st X509;
namespace net {
class CertVerifier;
+class SingleRequestCertVerifier;
class SSLCertRequestInfo;
class SSLConfig;
class SSLInfo;
@@ -33,16 +38,27 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
// settings.
SSLClientSocketOpenSSL(ClientSocketHandle* transport_socket,
const HostPortPair& host_and_port,
- const SSLConfig& ssl_config);
+ const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier);
~SSLClientSocketOpenSSL();
const HostPortPair& host_and_port() const { return host_and_port_; }
+<<<<<<< HEAD
#ifdef ANDROID
// Callback from the SSL layer to check which NPN protocol we are supporting
int SelectNextProtoCallback(unsigned char** out, unsigned char* outlen,
const unsigned char* in, unsigned int inlen);
#endif
+=======
+ // Callback from the SSL layer that indicates the remote server is requesting
+ // a certificate for this client.
+ int ClientCertRequestCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey);
+
+ // Callback from the SSL layer to check which NPN protocol we are supporting
+ int SelectNextProtoCallback(unsigned char** out, unsigned char* outlen,
+ const unsigned char* in, unsigned int inlen);
+>>>>>>> chromium.org at r10.0.621.0
// SSLClientSocket methods:
virtual void GetSSLInfo(SSLInfo* ssl_info);
@@ -58,7 +74,7 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
- virtual int GetPeerAddress(AddressList*) const;
+ virtual int GetPeerAddress(AddressList* address) const;
virtual const BoundNetLog& NetLog() const;
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
@@ -81,7 +97,6 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
int DoVerifyCert(int result);
int DoVerifyCertComplete(int result);
void DoConnectCallback(int result);
- void InvalidateSessionIfBadCertificate();
X509Certificate* UpdateServerCert();
void OnHandshakeIOComplete(int result);
@@ -130,7 +145,8 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
std::vector<scoped_refptr<X509Certificate> > client_certs_;
bool client_auth_cert_needed_;
- scoped_ptr<CertVerifier> verifier_;
+ CertVerifier* const cert_verifier_;
+ scoped_ptr<SingleRequestCertVerifier> verifier_;
CompletionCallbackImpl<SSLClientSocketOpenSSL> handshake_io_callback_;
// OpenSSL stuff
@@ -151,14 +167,19 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
STATE_VERIFY_CERT_COMPLETE,
};
State next_handshake_state_;
+<<<<<<< HEAD
#ifdef ANDROID
NextProtoStatus npn_status_;
std::string npn_proto_;
#endif
+=======
+ NextProtoStatus npn_status_;
+ std::string npn_proto_;
+>>>>>>> chromium.org at r10.0.621.0
BoundNetLog net_log_;
};
} // namespace net
-#endif // NET_SOCKET_SSL_CLIENT_SOCKET_OPENSSL_H_
+#endif // NET_SOCKET_SSL_CLIENT_SOCKET_OPENSSL_H_
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 54e5152..8002814 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -86,6 +86,7 @@ SSLConnectJob::SSLConnectJob(
HttpProxyClientSocketPool* http_proxy_pool,
ClientSocketFactory* client_socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -98,7 +99,8 @@ SSLConnectJob::SSLConnectJob(
socks_pool_(socks_pool),
http_proxy_pool_(http_proxy_pool),
client_socket_factory_(client_socket_factory),
- resolver_(host_resolver),
+ host_resolver_(host_resolver),
+ cert_verifier_(cert_verifier),
dnsrr_resolver_(dnsrr_resolver),
dns_cert_checker_(dns_cert_checker),
ssl_host_info_factory_(ssl_host_info_factory),
@@ -203,7 +205,7 @@ int SSLConnectJob::DoLoop(int result) {
int SSLConnectJob::DoTCPConnect() {
DCHECK(tcp_pool_);
- if (ssl_host_info_factory_ && SSLConfigService::snap_start_enabled()) {
+ if (ssl_host_info_factory_) {
ssl_host_info_.reset(
ssl_host_info_factory_->GetForHost(params_->host_and_port().host(),
params_->ssl_config()));
@@ -265,11 +267,12 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) {
// |GetAdditionalErrorState|, we can easily set the state.
if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
error_response_info_ = transport_socket_handle_->ssl_error_response_info();
- } else if (result == ERR_PROXY_AUTH_REQUESTED) {
+ } else if (result == ERR_PROXY_AUTH_REQUESTED ||
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
ClientSocket* socket = transport_socket_handle_->socket();
HttpProxyClientSocket* tunnel_socket =
static_cast<HttpProxyClientSocket*>(socket);
- error_response_info_ = *tunnel_socket->GetResponseInfo();
+ error_response_info_ = *tunnel_socket->GetConnectResponseInfo();
}
if (result < 0)
return result;
@@ -298,12 +301,18 @@ int SSLConnectJob::DoSSLConnect() {
ssl_socket_.reset(client_socket_factory_->CreateSSLClientSocket(
transport_socket_handle_.release(), params_->host_and_port(),
+<<<<<<< HEAD
params_->ssl_config(), ssl_host_info_.release(), dns_cert_checker_));
return ssl_socket_->Connect(&callback_
#ifdef ANDROID
, params_->ignore_limits()
#endif
);
+=======
+ params_->ssl_config(), ssl_host_info_.release(), cert_verifier_,
+ dns_cert_checker_));
+ return ssl_socket_->Connect(&callback_);
+>>>>>>> chromium.org at r10.0.621.0
}
int SSLConnectJob::DoSSLConnectComplete(int result) {
@@ -373,7 +382,7 @@ ConnectJob* SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
return new SSLConnectJob(group_name, request.params(), ConnectionTimeout(),
tcp_pool_, socks_pool_, http_proxy_pool_,
client_socket_factory_, host_resolver_,
- dnsrr_resolver_, dns_cert_checker_,
+ cert_verifier_, dnsrr_resolver_, dns_cert_checker_,
ssl_host_info_factory_, delegate, net_log_);
}
@@ -383,6 +392,7 @@ SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
HttpProxyClientSocketPool* http_proxy_pool,
ClientSocketFactory* client_socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -392,6 +402,7 @@ SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
http_proxy_pool_(http_proxy_pool),
client_socket_factory_(client_socket_factory),
host_resolver_(host_resolver),
+ cert_verifier_(cert_verifier),
dnsrr_resolver_(dnsrr_resolver),
dns_cert_checker_(dns_cert_checker),
ssl_host_info_factory_(ssl_host_info_factory),
@@ -419,6 +430,7 @@ SSLClientSocketPool::SSLClientSocketPool(
int max_sockets_per_group,
ClientSocketPoolHistograms* histograms,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -437,8 +449,8 @@ SSLClientSocketPool::SSLClientSocketPool(
base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout),
new SSLConnectJobFactory(tcp_pool, socks_pool, http_proxy_pool,
client_socket_factory, host_resolver,
- dnsrr_resolver, dns_cert_checker,
- ssl_host_info_factory,
+ cert_verifier, dnsrr_resolver,
+ dns_cert_checker, ssl_host_info_factory,
net_log)),
ssl_config_service_(ssl_config_service) {
if (ssl_config_service_)
@@ -492,6 +504,10 @@ void SSLClientSocketPool::CloseIdleSockets() {
base_.CloseIdleSockets();
}
+int SSLClientSocketPool::IdleSocketCount() const {
+ return base_.idle_socket_count();
+}
+
int SSLClientSocketPool::IdleSocketCountInGroup(
const std::string& group_name) const {
return base_.IdleSocketCountInGroup(group_name);
@@ -533,4 +549,12 @@ DictionaryValue* SSLClientSocketPool::GetInfoAsValue(
return dict;
}
+base::TimeDelta SSLClientSocketPool::ConnectionTimeout() const {
+ return base_.ConnectionTimeout();
+}
+
+ClientSocketPoolHistograms* SSLClientSocketPool::histograms() const {
+ return base_.histograms();
+}
+
} // namespace net
diff --git a/net/socket/ssl_client_socket_pool.h b/net/socket/ssl_client_socket_pool.h
index 3d332af..70da04f 100644
--- a/net/socket/ssl_client_socket_pool.h
+++ b/net/socket/ssl_client_socket_pool.h
@@ -22,6 +22,7 @@
namespace net {
+class CertVerifier;
class ClientSocketFactory;
class ConnectJobFactory;
class DnsCertProvenanceChecker;
@@ -101,6 +102,7 @@ class SSLConnectJob : public ConnectJob {
HttpProxyClientSocketPool* http_proxy_pool,
ClientSocketFactory* client_socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -150,7 +152,8 @@ class SSLConnectJob : public ConnectJob {
SOCKSClientSocketPool* const socks_pool_;
HttpProxyClientSocketPool* const http_proxy_pool_;
ClientSocketFactory* const client_socket_factory_;
- HostResolver* const resolver_;
+ HostResolver* const host_resolver_;
+ CertVerifier* const cert_verifier_;
DnsRRResolver* const dnsrr_resolver_;
DnsCertProvenanceChecker* dns_cert_checker_;
SSLHostInfoFactory* const ssl_host_info_factory_;
@@ -179,6 +182,7 @@ class SSLClientSocketPool : public ClientSocketPool,
int max_sockets_per_group,
ClientSocketPoolHistograms* histograms,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -215,9 +219,7 @@ class SSLClientSocketPool : public ClientSocketPool,
virtual void CloseIdleSockets();
- virtual int IdleSocketCount() const {
- return base_.idle_socket_count();
- }
+ virtual int IdleSocketCount() const;
virtual int IdleSocketCountInGroup(const std::string& group_name) const;
@@ -228,13 +230,9 @@ class SSLClientSocketPool : public ClientSocketPool,
const std::string& type,
bool include_nested_pools) const;
- virtual base::TimeDelta ConnectionTimeout() const {
- return base_.ConnectionTimeout();
- }
+ virtual base::TimeDelta ConnectionTimeout() const;
- virtual ClientSocketPoolHistograms* histograms() const {
- return base_.histograms();
- };
+ virtual ClientSocketPoolHistograms* histograms() const;
private:
// SSLConfigService::Observer methods:
@@ -253,6 +251,7 @@ class SSLClientSocketPool : public ClientSocketPool,
HttpProxyClientSocketPool* http_proxy_pool,
ClientSocketFactory* client_socket_factory,
HostResolver* host_resolver,
+ CertVerifier* cert_verifier,
DnsRRResolver* dnsrr_resolver,
DnsCertProvenanceChecker* dns_cert_checker,
SSLHostInfoFactory* ssl_host_info_factory,
@@ -274,6 +273,7 @@ class SSLClientSocketPool : public ClientSocketPool,
HttpProxyClientSocketPool* const http_proxy_pool_;
ClientSocketFactory* const client_socket_factory_;
HostResolver* const host_resolver_;
+ CertVerifier* const cert_verifier_;
DnsRRResolver* const dnsrr_resolver_;
DnsCertProvenanceChecker* const dns_cert_checker_;
SSLHostInfoFactory* const ssl_host_info_factory_;
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 247638b..37e21ca 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -10,6 +10,7 @@
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "net/base/auth.h"
+#include "net/base/cert_verifier.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
@@ -36,9 +37,11 @@ class SSLClientSocketPoolTest : public testing::Test {
protected:
SSLClientSocketPoolTest()
: host_resolver_(new MockHostResolver),
+ cert_verifier_(new CertVerifier),
http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault(
host_resolver_.get())),
session_(new HttpNetworkSession(host_resolver_.get(),
+ cert_verifier_.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -96,7 +99,8 @@ class SSLClientSocketPoolTest : public testing::Test {
kMaxSockets,
kMaxSocketsPerGroup,
ssl_histograms_.get(),
- NULL,
+ NULL /* host_resolver */,
+ NULL /* cert_verifier */,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -131,6 +135,7 @@ class SSLClientSocketPoolTest : public testing::Test {
MockClientSocketFactory socket_factory_;
scoped_ptr<HostResolver> host_resolver_;
+ scoped_ptr<CertVerifier> cert_verifier_;
scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
scoped_refptr<HttpNetworkSession> session_;
diff --git a/net/socket/ssl_client_socket_snapstart_unittest.cc b/net/socket/ssl_client_socket_snapstart_unittest.cc
index 13b2636..d782993 100644
--- a/net/socket/ssl_client_socket_snapstart_unittest.cc
+++ b/net/socket/ssl_client_socket_snapstart_unittest.cc
@@ -41,8 +41,8 @@ namespace net {
// pretends that certificate verification always succeeds.
class TestSSLHostInfo : public SSLHostInfo {
public:
- TestSSLHostInfo()
- : SSLHostInfo("example.com", kDefaultSSLConfig) {
+ explicit TestSSLHostInfo(CertVerifier* cert_verifier)
+ : SSLHostInfo("example.com", kDefaultSSLConfig, cert_verifier) {
if (!saved_.empty())
Parse(saved_);
cert_verification_complete_ = true;
@@ -121,7 +121,7 @@ class SSLClientSocketSnapStartTest : public PlatformTest {
// The listening socket is installed as the child's fd 3.
mapping.push_back(std::make_pair(listener, 3));
base::LaunchApp(args, mapping, false /* don't wait */, &child_);
- HANDLE_EINTR(close(listener));
+ ASSERT_EQ(0, HANDLE_EINTR(close(listener)));
}
// LoadDefaultCert returns the DER encoded default certificate.
@@ -194,7 +194,7 @@ class SSLClientSocketSnapStartTest : public PlatformTest {
scoped_ptr<SSLClientSocket> sock(
socket_factory_->CreateSSLClientSocket(
transport, HostPortPair("example.com", 443), ssl_config_,
- new TestSSLHostInfo()));
+ new TestSSLHostInfo(&cert_verifier_), &cert_verifier_));
TestCompletionCallback callback;
int rv = sock->Connect(&callback);
@@ -234,8 +234,9 @@ class SSLClientSocketSnapStartTest : public PlatformTest {
// SnapStartEventType extracts the type of Snap Start from the NetLog. See
// the SSL_SNAP_START_* defines in sslt.h
int SnapStartEventType() {
- const std::vector<CapturingNetLog::Entry>& entries = log_.entries();
- for (std::vector<CapturingNetLog::Entry>::const_iterator
+ CapturingNetLog::EntryList entries;
+ log_.GetEntries(&entries);
+ for (CapturingNetLog::EntryList::const_iterator
i = entries.begin(); i != entries.end(); i++) {
if (i->type == NetLog::TYPE_SSL_SNAP_START) {
scoped_ptr<Value> value(i->extra_parameters->ToValue());
@@ -253,8 +254,9 @@ class SSLClientSocketSnapStartTest : public PlatformTest {
// it's certificate validation with the optimistic validation from the
// SSLHostInfo.
bool DidMerge() {
- const std::vector<CapturingNetLog::Entry>& entries = log_.entries();
- for (std::vector<CapturingNetLog::Entry>::const_iterator
+ CapturingNetLog::EntryList entries;
+ log_.GetEntries(&entries);
+ for (CapturingNetLog::EntryList::const_iterator
i = entries.begin(); i != entries.end(); i++) {
if (i->type == NetLog::TYPE_SSL_VERIFICATION_MERGED)
return true;
@@ -263,6 +265,7 @@ class SSLClientSocketSnapStartTest : public PlatformTest {
}
base::ProcessHandle child_;
+ CertVerifier cert_verifier_;
ClientSocketFactory* const socket_factory_;
struct sockaddr_in remote_;
int client_;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index e736d5b..9ba5cbf 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -5,6 +5,7 @@
#include "net/socket/ssl_client_socket.h"
#include "net/base/address_list.h"
+#include "net/base/cert_verifier.h"
#include "net/base/host_resolver.h"
#include "net/base/io_buffer.h"
#include "net/base/net_log.h"
@@ -26,11 +27,24 @@ const net::SSLConfig kDefaultSSLConfig;
class SSLClientSocketTest : public PlatformTest {
public:
SSLClientSocketTest()
- : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
+ : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()),
+ cert_verifier_(new net::CertVerifier) {
}
protected:
+ net::SSLClientSocket* CreateSSLClientSocket(
+ net::ClientSocket* transport_socket,
+ const net::HostPortPair& host_and_port,
+ const net::SSLConfig& ssl_config) {
+ return socket_factory_->CreateSSLClientSocket(transport_socket,
+ host_and_port,
+ ssl_config,
+ NULL,
+ cert_verifier_.get());
+ }
+
net::ClientSocketFactory* socket_factory_;
+ scoped_ptr<net::CertVerifier> cert_verifier_;
};
//-----------------------------------------------------------------------------
@@ -67,18 +81,23 @@ TEST_F(SSLClientSocketTest, Connect) {
scoped_ptr<net::SSLClientSocket> sock(
socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ transport, test_server.host_port_pair(), kDefaultSSLConfig,
+ NULL, cert_verifier_.get()));
EXPECT_FALSE(sock->IsConnected());
rv = sock->Connect(&callback);
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
+ entries, 5, net::NetLog::TYPE_SSL_CONNECT));
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(net::OK, rv);
EXPECT_TRUE(sock->IsConnected());
- EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
sock->Disconnect();
EXPECT_FALSE(sock->IsConnected());
@@ -103,14 +122,17 @@ TEST_F(SSLClientSocketTest, ConnectExpired) {
EXPECT_EQ(net::OK, rv);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ kDefaultSSLConfig));
EXPECT_FALSE(sock->IsConnected());
rv = sock->Connect(&callback);
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
+ entries, 5, net::NetLog::TYPE_SSL_CONNECT));
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
@@ -120,7 +142,8 @@ TEST_F(SSLClientSocketTest, ConnectExpired) {
// test that the handshake has finished. This is because it may be
// desirable to disconnect the socket before showing a user prompt, since
// the user may take indefinitely long to respond.
- EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
}
TEST_F(SSLClientSocketTest, ConnectMismatched) {
@@ -142,15 +165,17 @@ TEST_F(SSLClientSocketTest, ConnectMismatched) {
EXPECT_EQ(net::OK, rv);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ kDefaultSSLConfig));
EXPECT_FALSE(sock->IsConnected());
rv = sock->Connect(&callback);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
+ entries, 5, net::NetLog::TYPE_SSL_CONNECT));
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
@@ -160,7 +185,8 @@ TEST_F(SSLClientSocketTest, ConnectMismatched) {
// test that the handshake has finished. This is because it may be
// desirable to disconnect the socket before showing a user prompt, since
// the user may take indefinitely long to respond.
- EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
}
// Attempt to connect to a page which requests a client certificate. It should
@@ -185,17 +211,22 @@ TEST_F(SSLClientSocketTest, FLAKY_ConnectClientAuthCertRequested) {
EXPECT_EQ(net::OK, rv);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ kDefaultSSLConfig));
EXPECT_FALSE(sock->IsConnected());
rv = sock->Connect(&callback);
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
+ entries, 5, net::NetLog::TYPE_SSL_CONNECT));
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
EXPECT_FALSE(sock->IsConnected());
}
@@ -227,22 +258,26 @@ TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) {
ssl_config.client_cert = NULL;
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), ssl_config, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ ssl_config));
EXPECT_FALSE(sock->IsConnected());
// Our test server accepts certificate-less connections.
// TODO(davidben): Add a test which requires them and verify the error.
rv = sock->Connect(&callback);
+
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
+ entries, 5, net::NetLog::TYPE_SSL_CONNECT));
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_EQ(net::OK, rv);
EXPECT_TRUE(sock->IsConnected());
- EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
sock->Disconnect();
EXPECT_FALSE(sock->IsConnected());
@@ -269,8 +304,8 @@ TEST_F(SSLClientSocketTest, Read) {
EXPECT_EQ(net::OK, rv);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ kDefaultSSLConfig));
rv = sock->Connect(&callback);
if (rv == net::ERR_IO_PENDING)
@@ -325,7 +360,8 @@ TEST_F(SSLClientSocketTest, Read_FullDuplex) {
scoped_ptr<net::SSLClientSocket> sock(
socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ transport, test_server.host_port_pair(), kDefaultSSLConfig,
+ NULL, cert_verifier_.get()));
rv = sock->Connect(&callback);
if (rv == net::ERR_IO_PENDING)
@@ -378,8 +414,8 @@ TEST_F(SSLClientSocketTest, Read_SmallChunks) {
EXPECT_EQ(net::OK, rv);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ kDefaultSSLConfig));
rv = sock->Connect(&callback);
if (rv == net::ERR_IO_PENDING)
@@ -428,8 +464,8 @@ TEST_F(SSLClientSocketTest, Read_Interrupted) {
EXPECT_EQ(net::OK, rv);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ kDefaultSSLConfig));
rv = sock->Connect(&callback);
if (rv == net::ERR_IO_PENDING)
@@ -498,23 +534,16 @@ TEST_F(SSLClientSocketTest, PrematureApplicationData) {
EXPECT_EQ(net::OK, rv);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ kDefaultSSLConfig));
rv = sock->Connect(&callback);
EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
}
-#if defined(USE_OPENSSL)
-// TODO(rsleevi): Not implemented for Schannel or OpenSSL. Schannel is
-// controlled by the SSL client socket factory, rather than a define, so it
-// cannot be conditionally disabled here. As Schannel is only used when
+// TODO(rsleevi): Not implemented for Schannel. As Schannel is only used when
// performing client authentication, it will not be tested here.
-#define MAYBE_CipherSuiteDisables DISABLED_CipherSuiteDisables
-#else
-#define MAYBE_CipherSuiteDisables CipherSuiteDisables
-#endif
-TEST_F(SSLClientSocketTest, MAYBE_CipherSuiteDisables) {
+TEST_F(SSLClientSocketTest, CipherSuiteDisables) {
// Rather than exhaustively disabling every RC4 ciphersuite defined at
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml,
// only disabling those cipher suites that the test server actually
@@ -547,14 +576,16 @@ TEST_F(SSLClientSocketTest, MAYBE_CipherSuiteDisables) {
ssl_config.disabled_cipher_suites.push_back(kCiphersToDisable[i]);
scoped_ptr<net::SSLClientSocket> sock(
- socket_factory_->CreateSSLClientSocket(
- transport, test_server.host_port_pair(), ssl_config, NULL));
+ CreateSSLClientSocket(transport, test_server.host_port_pair(),
+ ssl_config));
EXPECT_FALSE(sock->IsConnected());
rv = sock->Connect(&callback);
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
EXPECT_TRUE(net::LogContainsBeginEvent(
- log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
+ entries, 5, net::NetLog::TYPE_SSL_CONNECT));
// NSS has special handling that maps a handshake_failure alert received
// immediately after a client_hello to be a mismatched cipher suite error,
@@ -569,12 +600,13 @@ TEST_F(SSLClientSocketTest, MAYBE_CipherSuiteDisables) {
// The exact ordering differs between SSLClientSocketNSS (which issues an
// extra read) and SSLClientSocketMac (which does not). Just make sure the
// error appears somewhere in the log.
- net::ExpectLogContainsSomewhere(log.entries(), 0,
+ log.GetEntries(&entries);
+ net::ExpectLogContainsSomewhere(entries, 0,
net::NetLog::TYPE_SSL_HANDSHAKE_ERROR,
net::NetLog::PHASE_NONE);
// We cannot test sock->IsConnected(), as the NSS implementation disconnects
// the socket when it encounters an error, whereas other implementations
// leave it connected.
- EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
}
diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc
index 72d7492..1d8c039 100644
--- a/net/socket/ssl_client_socket_win.cc
+++ b/net/socket/ssl_client_socket_win.cc
@@ -8,8 +8,8 @@
#include <map>
#include "base/compiler_specific.h"
+#include "base/lazy_instance.h"
#include "base/lock.h"
-#include "base/singleton.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
@@ -110,12 +110,11 @@ static int MapSecurityError(SECURITY_STATUS err) {
//-----------------------------------------------------------------------------
// A bitmask consisting of these bit flags encodes which versions of the SSL
-// protocol (SSL 2.0, SSL 3.0, and TLS 1.0) are enabled.
+// protocol (SSL 3.0 and TLS 1.0) are enabled.
enum {
- SSL2 = 1 << 0,
- SSL3 = 1 << 1,
- TLS1 = 1 << 2,
- SSL_VERSION_MASKS = 1 << 3 // The number of SSL version bitmasks.
+ SSL3 = 1 << 0,
+ TLS1 = 1 << 1,
+ SSL_VERSION_MASKS = 1 << 2 // The number of SSL version bitmasks.
};
// CredHandleClass simply gives a default constructor and a destructor to
@@ -195,6 +194,9 @@ class CredHandleTable {
CredHandleMap client_cert_creds_;
};
+static base::LazyInstance<CredHandleTable> g_cred_handle_table(
+ base::LINKER_INITIALIZED);
+
// static
int CredHandleTable::InitializeHandle(CredHandle* handle,
PCCERT_CONTEXT client_cert,
@@ -210,8 +212,6 @@ int CredHandleTable::InitializeHandle(CredHandle* handle,
// The global system registry settings take precedence over the value of
// schannel_cred.grbitEnabledProtocols.
schannel_cred.grbitEnabledProtocols = 0;
- if (ssl_version_mask & SSL2)
- schannel_cred.grbitEnabledProtocols |= SP_PROT_SSL2;
if (ssl_version_mask & SSL3)
schannel_cred.grbitEnabledProtocols |= SP_PROT_SSL3;
if (ssl_version_mask & TLS1)
@@ -288,9 +288,9 @@ static int GetCredHandle(PCCERT_CONTEXT client_cert,
NOTREACHED();
return ERR_UNEXPECTED;
}
- return Singleton<CredHandleTable>::get()->GetHandle(client_cert,
- ssl_version_mask,
- handle_ptr);
+ return g_cred_handle_table.Get().GetHandle(client_cert,
+ ssl_version_mask,
+ handle_ptr);
}
//-----------------------------------------------------------------------------
@@ -359,6 +359,9 @@ class ClientCertStore {
HCERTSTORE store_;
};
+static base::LazyInstance<ClientCertStore> g_client_cert_store(
+ base::LINKER_INITIALIZED);
+
//-----------------------------------------------------------------------------
// Size of recv_buffer_
@@ -373,7 +376,8 @@ static const int kRecvBufferSize = (5 + 16*1024 + 64);
SSLClientSocketWin::SSLClientSocketWin(ClientSocketHandle* transport_socket,
const HostPortPair& host_and_port,
- const SSLConfig& ssl_config)
+ const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier)
: ALLOW_THIS_IN_INITIALIZER_LIST(
handshake_io_callback_(this,
&SSLClientSocketWin::OnHandshakeIOComplete)),
@@ -390,6 +394,7 @@ SSLClientSocketWin::SSLClientSocketWin(ClientSocketHandle* transport_socket,
user_write_callback_(NULL),
user_write_buf_len_(0),
next_state_(STATE_NONE),
+ cert_verifier_(cert_verifier),
creds_(NULL),
isc_status_(SEC_E_OK),
payload_send_buffer_len_(0),
@@ -510,7 +515,7 @@ void SSLClientSocketWin::GetSSLCertRequestInfo(
// 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 =
- Singleton<ClientCertStore>::get()->CopyCertContext(cert_context);
+ g_client_cert_store.Get().CopyCertContext(cert_context);
if (!cert_context2) {
NOTREACHED();
continue;
@@ -568,8 +573,6 @@ int SSLClientSocketWin::Connect(CompletionCallback* callback
int SSLClientSocketWin::InitializeSSLContext() {
int ssl_version_mask = 0;
- if (ssl_config_.ssl2_enabled)
- ssl_version_mask |= SSL2;
if (ssl_config_.ssl3_enabled)
ssl_version_mask |= SSL3;
if (ssl_config_.tls1_enabled)
@@ -1131,7 +1134,7 @@ int SSLClientSocketWin::DoVerifyCert() {
flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
if (ssl_config_.verify_ev_cert)
flags |= X509Certificate::VERIFY_EV_CERT;
- verifier_.reset(new CertVerifier);
+ verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
&server_cert_verify_result_,
&handshake_io_callback_);
diff --git a/net/socket/ssl_client_socket_win.h b/net/socket/ssl_client_socket_win.h
index 11d28a2..b927f8d 100644
--- a/net/socket/ssl_client_socket_win.h
+++ b/net/socket/ssl_client_socket_win.h
@@ -28,6 +28,7 @@ class BoundNetLog;
class CertVerifier;
class ClientSocketHandle;
class HostPortPair;
+class SingleRequestCertVerifier;
// An SSL client socket implemented with the Windows Schannel.
class SSLClientSocketWin : public SSLClientSocket {
@@ -40,7 +41,8 @@ class SSLClientSocketWin : public SSLClientSocket {
// the SSL settings.
SSLClientSocketWin(ClientSocketHandle* transport_socket,
const HostPortPair& host_and_port,
- const SSLConfig& ssl_config);
+ const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier);
~SSLClientSocketWin();
// SSLClientSocket methods:
@@ -149,7 +151,8 @@ class SSLClientSocketWin : public SSLClientSocket {
SecPkgContext_StreamSizes stream_sizes_;
scoped_refptr<X509Certificate> server_cert_;
- scoped_ptr<CertVerifier> verifier_;
+ CertVerifier* const cert_verifier_;
+ scoped_ptr<SingleRequestCertVerifier> verifier_;
CertVerifyResult server_cert_verify_result_;
CredHandle* creds_;
diff --git a/net/socket/ssl_host_info.cc b/net/socket/ssl_host_info.cc
index 3fa9e35..f95c851 100644
--- a/net/socket/ssl_host_info.cc
+++ b/net/socket/ssl_host_info.cc
@@ -5,11 +5,12 @@
#include "net/socket/ssl_host_info.h"
#include "base/metrics/histogram.h"
+#include "base/pickle.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"
+<<<<<<< HEAD
#ifdef ANDROID
// the android platform build system use a fixed include path relative to the
// top directory (root of the source tree).
@@ -17,6 +18,8 @@
#else
#include "net/socket/ssl_host_info.pb.h"
#endif
+=======
+>>>>>>> chromium.org at r10.0.621.0
namespace net {
@@ -27,9 +30,16 @@ SSLHostInfo::State::State()
SSLHostInfo::State::~State() {}
+void SSLHostInfo::State::Clear() {
+ certs.clear();
+ server_hello.clear();
+ npn_valid = false;
+}
+
SSLHostInfo::SSLHostInfo(
const std::string& hostname,
- const SSLConfig& ssl_config)
+ const SSLConfig& ssl_config,
+ CertVerifier* cert_verifier)
: cert_verification_complete_(false),
cert_verification_error_(ERR_CERT_INVALID),
hostname_(hostname),
@@ -37,6 +47,7 @@ SSLHostInfo::SSLHostInfo(
cert_verification_callback_(NULL),
rev_checking_enabled_(ssl_config.rev_checking_enabled),
verify_ev_cert_(ssl_config.verify_ev_cert),
+ verifier_(cert_verifier),
callback_(new CancelableCompletionCallback<SSLHostInfo>(
ALLOW_THIS_IN_INITIALIZER_LIST(this),
&SSLHostInfo::VerifyCallback)) {
@@ -45,36 +56,6 @@ SSLHostInfo::SSLHostInfo(
SSLHostInfo::~SSLHostInfo() {}
-// This array and the next two functions serve to map between the internal NPN
-// status enum (which might change across versions) and the protocol buffer
-// based enum (which will not).
-static const struct {
- SSLClientSocket::NextProtoStatus npn_status;
- SSLHostInfoProto::NextProtoStatus proto_status;
-} kNPNStatusMapping[] = {
- { SSLClientSocket::kNextProtoUnsupported, SSLHostInfoProto::UNSUPPORTED },
- { SSLClientSocket::kNextProtoNegotiated, SSLHostInfoProto::NEGOTIATED },
- { SSLClientSocket::kNextProtoNoOverlap, SSLHostInfoProto::NO_OVERLAP },
-};
-
-static SSLClientSocket::NextProtoStatus NPNStatusFromProtoStatus(
- SSLHostInfoProto::NextProtoStatus proto_status) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1; i++) {
- if (kNPNStatusMapping[i].proto_status == proto_status)
- return kNPNStatusMapping[i].npn_status;
- }
- return kNPNStatusMapping[ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1].npn_status;
-}
-
-static SSLHostInfoProto::NextProtoStatus ProtoStatusFromNPNStatus(
- SSLClientSocket::NextProtoStatus npn_status) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1; i++) {
- if (kNPNStatusMapping[i].npn_status == npn_status)
- return kNPNStatusMapping[i].proto_status;
- }
- return kNPNStatusMapping[ARRAYSIZE_UNSAFE(kNPNStatusMapping)-1].proto_status;
-}
-
const SSLHostInfo::State& SSLHostInfo::state() const {
return state_;
}
@@ -84,25 +65,49 @@ SSLHostInfo::State* SSLHostInfo::mutable_state() {
}
bool SSLHostInfo::Parse(const std::string& data) {
- SSLHostInfoProto proto;
State* state = mutable_state();
- state->certs.clear();
- state->server_hello.clear();
- state->npn_valid = false;
+ state->Clear();
cert_verification_complete_ = false;
- if (!proto.ParseFromString(data))
+ bool r = ParseInner(data);
+ if (!r)
+ state->Clear();
+ return r;
+}
+
+bool SSLHostInfo::ParseInner(const std::string& data) {
+ State* state = mutable_state();
+
+ Pickle p(data.data(), data.size());
+ void* iter = NULL;
+
+ int num_der_certs;
+ if (!p.ReadInt(&iter, &num_der_certs) ||
+ num_der_certs < 0) {
return false;
+ }
- for (int i = 0; i < proto.certificate_der_size(); i++)
- state->certs.push_back(proto.certificate_der(i));
- if (proto.has_server_hello())
- state->server_hello = proto.server_hello();
- if (proto.has_npn_status() && proto.has_npn_protocol()) {
- state->npn_valid = true;
- state->npn_status = NPNStatusFromProtoStatus(proto.npn_status());
- state->npn_protocol = proto.npn_protocol();
+ for (int i = 0; i < num_der_certs; i++) {
+ std::string der_cert;
+ if (!p.ReadString(&iter, &der_cert))
+ return false;
+ state->certs.push_back(der_cert);
+ }
+
+ if (!p.ReadString(&iter, &state->server_hello))
+ return false;
+
+ if (!p.ReadBool(&iter, &state->npn_valid))
+ return false;
+
+ if (state->npn_valid) {
+ int status;
+ if (!p.ReadInt(&iter, &status) ||
+ !p.ReadString(&iter, &state->npn_protocol)) {
+ return false;
+ }
+ state->npn_status = static_cast<SSLClientSocket::NextProtoStatus>(status);
}
if (state->certs.size() > 0) {
@@ -116,13 +121,13 @@ bool SSLHostInfo::Parse(const std::string& data) {
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);
- }
+ verification_end_time_ = base::TimeTicks();
+ int rv = verifier_.Verify(cert_.get(), hostname_, flags,
+ &cert_verify_result_, callback_);
+ if (rv != ERR_IO_PENDING)
+ VerifyCallback(rv);
} else {
cert_parsing_failed_ = true;
DCHECK(!cert_verification_callback_);
@@ -133,21 +138,42 @@ bool SSLHostInfo::Parse(const std::string& data) {
}
std::string SSLHostInfo::Serialize() const {
- SSLHostInfoProto proto;
+ Pickle p(sizeof(Pickle::Header));
+
+ static const unsigned kMaxCertificatesSize = 32 * 1024;
+ unsigned der_certs_size = 0;
for (std::vector<std::string>::const_iterator
i = state_.certs.begin(); i != state_.certs.end(); i++) {
- proto.add_certificate_der(*i);
+ der_certs_size += i->size();
+ }
+
+ // We don't care to save the certificates over a certain size.
+ if (der_certs_size > kMaxCertificatesSize)
+ return "";
+
+ if (!p.WriteInt(state_.certs.size()))
+ return "";
+
+ for (std::vector<std::string>::const_iterator
+ i = state_.certs.begin(); i != state_.certs.end(); i++) {
+ if (!p.WriteString(*i))
+ return "";
+ }
+
+ if (!p.WriteString(state_.server_hello) ||
+ !p.WriteBool(state_.npn_valid)) {
+ return "";
}
- if (!state_.server_hello.empty())
- proto.set_server_hello(state_.server_hello);
if (state_.npn_valid) {
- proto.set_npn_status(ProtoStatusFromNPNStatus(state_.npn_status));
- proto.set_npn_protocol(state_.npn_protocol);
+ if (!p.WriteInt(state_.npn_status) ||
+ !p.WriteString(state_.npn_protocol)) {
+ return "";
+ }
}
- return proto.SerializeAsString();
+ return std::string(reinterpret_cast<const char *>(p.data()), p.size());
}
const CertVerifyResult& SSLHostInfo::cert_verify_result() const {
@@ -170,6 +196,7 @@ void SSLHostInfo::VerifyCallback(int rv) {
const base::TimeDelta duration = now - verification_start_time();
UMA_HISTOGRAM_TIMES("Net.SSLHostInfoVerificationTimeMs", duration);
VLOG(1) << "Verification took " << duration.InMilliseconds() << "ms";
+ verification_end_time_ = now;
cert_verification_complete_ = true;
cert_verification_error_ = rv;
if (cert_verification_callback_) {
diff --git a/net/socket/ssl_host_info.h b/net/socket/ssl_host_info.h
index 10b8cb6..8f1502b 100644
--- a/net/socket/ssl_host_info.h
+++ b/net/socket/ssl_host_info.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_SOCKET_SSL_HOST_INFO_H
-#define NET_SOCKET_SSL_HOST_INFO_H
+#ifndef NET_SOCKET_SSL_HOST_INFO_H_
+#define NET_SOCKET_SSL_HOST_INFO_H_
#include <string>
#include <vector>
@@ -11,13 +11,13 @@
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
+#include "net/base/cert_verifier.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;
@@ -27,7 +27,9 @@ struct SSLConfig;
// certificates.
class SSLHostInfo {
public:
- SSLHostInfo(const std::string& hostname, const SSLConfig& ssl_config);
+ SSLHostInfo(const std::string& hostname,
+ const SSLConfig& ssl_config,
+ CertVerifier *certVerifier);
virtual ~SSLHostInfo();
// Start will commence the lookup. This must be called before any other
@@ -58,6 +60,8 @@ class SSLHostInfo {
State();
~State();
+ void Clear();
+
// 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;
@@ -85,15 +89,19 @@ class SSLHostInfo {
// 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.
+ // 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_;
}
+ base::TimeTicks verification_end_time() const {
+ return verification_end_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
@@ -108,6 +116,9 @@ class SSLHostInfo {
// This is the callback function which the CertVerifier calls via |callback_|.
void VerifyCallback(int rv);
+ // ParseInner is a helper function for Parse.
+ bool ParseInner(const std::string& data);
+
// This is the hostname that we'll validate the certificates against.
const std::string hostname_;
bool cert_parsing_failed_;
@@ -116,8 +127,9 @@ class SSLHostInfo {
bool rev_checking_enabled_;
bool verify_ev_cert_;
base::TimeTicks verification_start_time_;
+ base::TimeTicks verification_end_time_;
CertVerifyResult cert_verify_result_;
- scoped_ptr<CertVerifier> verifier_;
+ SingleRequestCertVerifier verifier_;
scoped_refptr<X509Certificate> cert_;
scoped_refptr<CancelableCompletionCallback<SSLHostInfo> > callback_;
};
@@ -134,4 +146,4 @@ class SSLHostInfoFactory {
} // namespace net
-#endif // NET_SOCKET_SSL_HOST_INFO_H
+#endif // NET_SOCKET_SSL_HOST_INFO_H_
diff --git a/net/socket/ssl_host_info.proto b/net/socket/ssl_host_info.proto
deleted file mode 100644
index d74a872..0000000
--- a/net/socket/ssl_host_info.proto
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package net;
-
-// SSLHostInfoProto contains information which we store about a given HTTPS
-// server.
-message SSLHostInfoProto {
- // The certificate chain, as returned by the server, as a series of DER
- // encoded X.509 certificates.
- repeated bytes certificate_der = 1;
- // The contents of the server's ServerHello message. Needed in order to
- // predict its response in the case of Snap Start.
- optional bytes server_hello = 2;
-
- // This is a mirror of SSLClientSocket::NextProtoStatus. We use this in order
- // to be robust against changes to that enum, which isn't required to be
- // stable across versions. See the comments there for details.
- enum NextProtoStatus {
- UNSUPPORTED = 0;
- NEGOTIATED = 1;
- NO_OVERLAP = 2;
- }
-
- // When doing Snap Start, we also need to know what protocol we expect the
- // server to negotiate.
- optional NextProtoStatus npn_status = 3;
- optional bytes npn_protocol = 4;
-};
diff --git a/net/socket/ssl_server_socket.h b/net/socket/ssl_server_socket.h
new file mode 100644
index 0000000..b689c71
--- /dev/null
+++ b/net/socket/ssl_server_socket.h
@@ -0,0 +1,53 @@
+// 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_SSL_SERVER_SOCKET_H_
+#define NET_SOCKET_SSL_SERVER_SOCKET_H_
+
+#include "base/basictypes.h"
+#include "net/base/completion_callback.h"
+#include "net/socket/socket.h"
+
+namespace base {
+class RSAPrivateKey;
+} // namespace base
+
+namespace net {
+
+class IOBuffer;
+struct SSLConfig;
+class X509Certificate;
+
+// SSLServerSocket takes an already connected socket and performs SSL on top of
+// it.
+//
+// This class is designed to work in a peer-to-peer connection and is not
+// intended to be used as a standalone SSL server.
+class SSLServerSocket : public Socket {
+ public:
+ virtual ~SSLServerSocket() {}
+
+ // Performs an SSL server handshake on the existing socket. The given socket
+ // must have already been connected.
+ //
+ // Accept either returns ERR_IO_PENDING, in which case the given callback
+ // will be called in the future with the real result, or it completes
+ // synchronously, returning the result immediately.
+ virtual int Accept(CompletionCallback* callback) = 0;
+};
+
+// Creates an SSL server socket using an already connected socket. A certificate
+// and private key needs to be provided.
+//
+// This created server socket will take ownership of |socket|. However |key|
+// is copied.
+// TODO(hclam): Defines ServerSocketFactory to create SSLServerSocket. This will
+// make mocking easier.
+SSLServerSocket* CreateSSLServerSocket(
+ Socket* socket, X509Certificate* certificate, base::RSAPrivateKey* key,
+ const SSLConfig& ssl_config);
+
+} // namespace net
+
+#endif // NET_SOCKET_SSL_SERVER_SOCKET_NSS_H_
diff --git a/net/socket/ssl_server_socket_nss.cc b/net/socket/ssl_server_socket_nss.cc
new file mode 100644
index 0000000..2e47fb8
--- /dev/null
+++ b/net/socket/ssl_server_socket_nss.cc
@@ -0,0 +1,677 @@
+// 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/ssl_server_socket_nss.h"
+
+#if defined(OS_WIN)
+#include <winsock2.h>
+#endif
+
+#if defined(USE_SYSTEM_SSL)
+#include <dlfcn.h>
+#endif
+#if defined(OS_MACOSX)
+#include <Security/Security.h>
+#endif
+#include <certdb.h>
+#include <cryptohi.h>
+#include <hasht.h>
+#include <keyhi.h>
+#include <nspr.h>
+#include <nss.h>
+#include <pk11pub.h>
+#include <secerr.h>
+#include <sechash.h>
+#include <ssl.h>
+#include <sslerr.h>
+#include <sslproto.h>
+
+#include <limits>
+
+#include "base/crypto/rsa_private_key.h"
+#include "base/nss_util_internal.h"
+#include "base/ref_counted.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/ocsp/nss_ocsp.h"
+#include "net/socket/nss_ssl_util.h"
+#include "net/socket/ssl_error_params.h"
+
+static const int kRecvBufferSize = 4096;
+
+#define GotoState(s) next_handshake_state_ = s
+
+namespace net {
+
+SSLServerSocket* CreateSSLServerSocket(
+ Socket* socket, X509Certificate* cert, base::RSAPrivateKey* key,
+ const SSLConfig& ssl_config) {
+ return new SSLServerSocketNSS(socket, cert, key, ssl_config);
+}
+
+SSLServerSocketNSS::SSLServerSocketNSS(
+ Socket* transport_socket,
+ scoped_refptr<X509Certificate> cert,
+ base::RSAPrivateKey* key,
+ const SSLConfig& ssl_config)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
+ this, &SSLServerSocketNSS::BufferSendComplete)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
+ this, &SSLServerSocketNSS::BufferRecvComplete)),
+ transport_send_busy_(false),
+ transport_recv_busy_(false),
+ user_accept_callback_(NULL),
+ user_read_callback_(NULL),
+ user_write_callback_(NULL),
+ nss_fd_(NULL),
+ nss_bufs_(NULL),
+ transport_socket_(transport_socket),
+ ssl_config_(ssl_config),
+ cert_(cert),
+ next_handshake_state_(STATE_NONE),
+ completed_handshake_(false) {
+ ssl_config_.false_start_enabled = false;
+ ssl_config_.ssl3_enabled = true;
+ ssl_config_.tls1_enabled = true;
+
+ // TODO(hclam): Need a better way to clone a key.
+ std::vector<uint8> key_bytes;
+ CHECK(key->ExportPrivateKey(&key_bytes));
+ key_.reset(base::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
+ CHECK(key_.get());
+}
+
+SSLServerSocketNSS::~SSLServerSocketNSS() {
+ if (nss_fd_ != NULL) {
+ PR_Close(nss_fd_);
+ nss_fd_ = NULL;
+ }
+}
+
+int SSLServerSocketNSS::Init() {
+ // Initialize the NSS SSL library in a threadsafe way. This also
+ // initializes the NSS base library.
+ EnsureNSSSSLInit();
+ if (!NSS_IsInitialized())
+ return ERR_UNEXPECTED;
+#if !defined(OS_MACOSX) && !defined(OS_WIN)
+ // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
+ // by MessageLoopForIO::current().
+ // X509Certificate::Verify() runs on a worker thread of CertVerifier.
+ EnsureOCSPInit();
+#endif
+
+ return OK;
+}
+
+int SSLServerSocketNSS::Accept(CompletionCallback* callback) {
+ net_log_.BeginEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
+
+ int rv = Init();
+ if (rv != OK) {
+ LOG(ERROR) << "Failed to initialize NSS";
+ net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
+ return rv;
+ }
+
+ rv = InitializeSSLOptions();
+ if (rv != OK) {
+ LOG(ERROR) << "Failed to initialize SSL options";
+ net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
+ return rv;
+ }
+
+ // Set peer address. TODO(hclam): This should be in a separate method.
+ PRNetAddr peername;
+ memset(&peername, 0, sizeof(peername));
+ peername.raw.family = AF_INET;
+ memio_SetPeerName(nss_fd_, &peername);
+
+ GotoState(STATE_HANDSHAKE);
+ rv = DoHandshakeLoop(net::OK);
+ if (rv == ERR_IO_PENDING) {
+ user_accept_callback_ = callback;
+ } else {
+ net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
+ }
+
+ return rv > OK ? OK : rv;
+}
+
+int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback) {
+ DCHECK(!user_read_callback_);
+ DCHECK(!user_accept_callback_);
+ DCHECK(!user_read_buf_);
+ DCHECK(nss_bufs_);
+
+ user_read_buf_ = buf;
+ user_read_buf_len_ = buf_len;
+
+ DCHECK(completed_handshake_);
+
+ int rv = DoReadLoop(OK);
+
+ if (rv == ERR_IO_PENDING) {
+ user_read_callback_ = callback;
+ } else {
+ user_read_buf_ = NULL;
+ user_read_buf_len_ = 0;
+ }
+ return rv;
+}
+
+int SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback) {
+ DCHECK(!user_write_callback_);
+ DCHECK(!user_write_buf_);
+ DCHECK(nss_bufs_);
+
+ user_write_buf_ = buf;
+ user_write_buf_len_ = buf_len;
+
+ int rv = DoWriteLoop(OK);
+
+ if (rv == ERR_IO_PENDING) {
+ user_write_callback_ = callback;
+ } else {
+ user_write_buf_ = NULL;
+ user_write_buf_len_ = 0;
+ }
+ return rv;
+}
+
+// static
+// NSS calls this if an incoming certificate needs to be verified.
+// Do nothing but return SECSuccess.
+// This is called only in full handshake mode.
+// Peer certificate is retrieved in HandshakeCallback() later, which is called
+// in full handshake mode or in resumption handshake mode.
+SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
+ PRFileDesc* socket,
+ PRBool checksig,
+ PRBool is_server) {
+ // TODO(hclam): Implement.
+ // Tell NSS to not verify the certificate.
+ return SECSuccess;
+}
+
+// static
+// NSS calls this when handshake is completed.
+// After the SSL handshake is finished we need to verify the certificate.
+void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
+ void* arg) {
+ // TODO(hclam): Implement.
+}
+
+int SSLServerSocketNSS::InitializeSSLOptions() {
+ // Transport connected, now hook it up to nss
+ // TODO(port): specify rx and tx buffer sizes separately
+ nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
+ if (nss_fd_ == NULL) {
+ return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
+ }
+
+ // Grab pointer to buffers
+ nss_bufs_ = memio_GetSecret(nss_fd_);
+
+ /* Create SSL state machine */
+ /* Push SSL onto our fake I/O socket */
+ nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
+ if (nss_fd_ == NULL) {
+ LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
+ return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
+ }
+ // TODO(port): set more ssl options! Check errors!
+
+ int rv;
+
+ rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, PR_TRUE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
+ return ERR_UNEXPECTED;
+ }
+
+ for (std::vector<uint16>::const_iterator it =
+ ssl_config_.disabled_cipher_suites.begin();
+ it != ssl_config_.disabled_cipher_suites.end(); ++it) {
+ // This will fail if the specified cipher is not implemented by NSS, but
+ // the failure is harmless.
+ SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
+ }
+
+ // Server socket doesn't need session tickets.
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(
+ net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
+ }
+
+ // Doing this will force PR_Accept perform handshake as server.
+ rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_OptionSet(nss_fd_, SSL_NO_CACHE, PR_TRUE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_NO_CACHE");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_ConfigureServerSessionIDCache", "");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
+ return ERR_UNEXPECTED;
+ }
+
+ rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
+ return ERR_UNEXPECTED;
+ }
+
+ // Get a certificate of CERTCertificate structure.
+ std::string der_string;
+ if (!cert_->GetDEREncoded(&der_string))
+ return ERR_UNEXPECTED;
+
+ SECItem der_cert;
+ der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
+ der_string.data()));
+ der_cert.len = der_string.length();
+ der_cert.type = siDERCertBuffer;
+
+ // Parse into a CERTCertificate structure.
+ CERTCertificate* cert = CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
+
+ // Get a key of SECKEYPrivateKey* structure.
+ std::vector<uint8> key_vector;
+ if (!key_->ExportPrivateKey(&key_vector)) {
+ CERT_DestroyCertificate(cert);
+ return ERR_UNEXPECTED;
+ }
+
+ SECKEYPrivateKeyStr* private_key = NULL;
+ PK11SlotInfo *slot = base::GetDefaultNSSKeySlot();
+ if (!slot) {
+ CERT_DestroyCertificate(cert);
+ return ERR_UNEXPECTED;
+ }
+
+ SECItem der_private_key_info;
+ der_private_key_info.data =
+ const_cast<unsigned char*>(&key_vector.front());
+ der_private_key_info.len = key_vector.size();
+ rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+ slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
+ KU_DIGITAL_SIGNATURE, &private_key, NULL);
+ PK11_FreeSlot(slot);
+ if (rv != SECSuccess) {
+ CERT_DestroyCertificate(cert);
+ return ERR_UNEXPECTED;
+ }
+
+ // Assign server certificate and private key.
+ SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
+ rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
+ CERT_DestroyCertificate(cert);
+ SECKEY_DestroyPrivateKey(private_key);
+
+ if (rv != SECSuccess) {
+ PRErrorCode prerr = PR_GetError();
+ LOG(ERROR) << "Failed to config SSL server: " << prerr;
+ LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
+ return ERR_UNEXPECTED;
+ }
+
+ // Tell SSL we're a server; needed if not letting NSPR do socket I/O
+ rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
+ return ERR_UNEXPECTED;
+ }
+
+ return OK;
+}
+
+// Return 0 for EOF,
+// > 0 for bytes transferred immediately,
+// < 0 for error (or the non-error ERR_IO_PENDING).
+int SSLServerSocketNSS::BufferSend(void) {
+ if (transport_send_busy_)
+ return ERR_IO_PENDING;
+
+ const char* buf1;
+ const char* buf2;
+ unsigned int len1, len2;
+ memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
+ const unsigned int len = len1 + len2;
+
+ int rv = 0;
+ if (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,
+ &buffer_send_callback_);
+ if (rv == ERR_IO_PENDING) {
+ transport_send_busy_ = true;
+ } else {
+ memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
+ }
+ }
+
+ return rv;
+}
+
+void SSLServerSocketNSS::BufferSendComplete(int result) {
+ memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
+ transport_send_busy_ = false;
+ OnSendComplete(result);
+}
+
+int SSLServerSocketNSS::BufferRecv(void) {
+ if (transport_recv_busy_) return ERR_IO_PENDING;
+
+ char *buf;
+ int nb = memio_GetReadParams(nss_bufs_, &buf);
+ int rv;
+ if (!nb) {
+ // buffer too full to read into, so no I/O possible at moment
+ rv = ERR_IO_PENDING;
+ } else {
+ recv_buffer_ = new IOBuffer(nb);
+ rv = transport_socket_->Read(recv_buffer_, nb, &buffer_recv_callback_);
+ if (rv == ERR_IO_PENDING) {
+ transport_recv_busy_ = true;
+ } else {
+ if (rv > 0)
+ memcpy(buf, recv_buffer_->data(), rv);
+ memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
+ recv_buffer_ = NULL;
+ }
+ }
+ return rv;
+}
+
+void SSLServerSocketNSS::BufferRecvComplete(int result) {
+ if (result > 0) {
+ char *buf;
+ memio_GetReadParams(nss_bufs_, &buf);
+ memcpy(buf, recv_buffer_->data(), result);
+ }
+ recv_buffer_ = NULL;
+ memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
+ transport_recv_busy_ = false;
+ OnRecvComplete(result);
+}
+
+void SSLServerSocketNSS::OnSendComplete(int result) {
+ if (next_handshake_state_ == STATE_HANDSHAKE) {
+ // In handshake phase.
+ OnHandshakeIOComplete(result);
+ return;
+ }
+
+ if (!user_write_buf_ || !completed_handshake_)
+ return;
+
+ int rv = DoWriteLoop(result);
+ if (rv != ERR_IO_PENDING)
+ DoWriteCallback(rv);
+}
+
+void SSLServerSocketNSS::OnRecvComplete(int result) {
+ if (next_handshake_state_ == STATE_HANDSHAKE) {
+ // In handshake phase.
+ OnHandshakeIOComplete(result);
+ return;
+ }
+
+ // Network layer received some data, check if client requested to read
+ // decrypted data.
+ if (!user_read_buf_ || !completed_handshake_)
+ return;
+
+ int rv = DoReadLoop(result);
+ if (rv != ERR_IO_PENDING)
+ DoReadCallback(rv);
+}
+
+void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
+ int rv = DoHandshakeLoop(result);
+ if (rv != ERR_IO_PENDING) {
+ net_log_.EndEvent(net::NetLog::TYPE_SSL_ACCEPT, NULL);
+ if (user_accept_callback_)
+ DoAcceptCallback(rv);
+ }
+}
+
+void SSLServerSocketNSS::DoAcceptCallback(int rv) {
+ DCHECK_NE(rv, ERR_IO_PENDING);
+
+ CompletionCallback* c = user_accept_callback_;
+ user_accept_callback_ = NULL;
+ c->Run(rv > OK ? OK : rv);
+}
+
+void SSLServerSocketNSS::DoReadCallback(int rv) {
+ DCHECK(rv != ERR_IO_PENDING);
+ DCHECK(user_read_callback_);
+
+ // Since Run may result in Read being called, clear |user_read_callback_|
+ // up front.
+ CompletionCallback* c = user_read_callback_;
+ user_read_callback_ = NULL;
+ user_read_buf_ = NULL;
+ user_read_buf_len_ = 0;
+ c->Run(rv);
+}
+
+void SSLServerSocketNSS::DoWriteCallback(int rv) {
+ DCHECK(rv != ERR_IO_PENDING);
+ DCHECK(user_write_callback_);
+
+ // Since Run may result in Write being called, clear |user_write_callback_|
+ // up front.
+ CompletionCallback* c = user_write_callback_;
+ user_write_callback_ = NULL;
+ user_write_buf_ = NULL;
+ user_write_buf_len_ = 0;
+ c->Run(rv);
+}
+
+// Do network I/O between the given buffer and the given socket.
+// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
+bool SSLServerSocketNSS::DoTransportIO() {
+ bool network_moved = false;
+ if (nss_bufs_ != NULL) {
+ int nsent = BufferSend();
+ int nreceived = BufferRecv();
+ network_moved = (nsent > 0 || nreceived >= 0);
+ }
+ return network_moved;
+}
+
+int SSLServerSocketNSS::DoPayloadRead() {
+ DCHECK(user_read_buf_);
+ DCHECK_GT(user_read_buf_len_, 0);
+ int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
+ if (rv >= 0)
+ return rv;
+ PRErrorCode prerr = PR_GetError();
+ if (prerr == PR_WOULD_BLOCK_ERROR) {
+ return ERR_IO_PENDING;
+ }
+ rv = MapNSSError(prerr);
+ net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
+ make_scoped_refptr(new SSLErrorParams(rv, prerr)));
+ return rv;
+}
+
+int SSLServerSocketNSS::DoPayloadWrite() {
+ DCHECK(user_write_buf_);
+ int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
+ if (rv >= 0)
+ return rv;
+ PRErrorCode prerr = PR_GetError();
+ if (prerr == PR_WOULD_BLOCK_ERROR) {
+ return ERR_IO_PENDING;
+ }
+ rv = MapNSSError(prerr);
+ net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
+ make_scoped_refptr(new SSLErrorParams(rv, prerr)));
+ return rv;
+}
+
+int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
+ bool network_moved;
+ int rv = last_io_result;
+ do {
+ // Default to STATE_NONE for next state.
+ // (This is a quirk carried over from the windows
+ // implementation. It makes reading the logs a bit harder.)
+ // State handlers can and often do call GotoState just
+ // to stay in the current state.
+ State state = next_handshake_state_;
+ GotoState(STATE_NONE);
+ switch (state) {
+ case STATE_NONE:
+ // we're just pumping data between the buffer and the network
+ break;
+ case STATE_HANDSHAKE:
+ rv = DoHandshake();
+ break;
+ default:
+ rv = ERR_UNEXPECTED;
+ LOG(DFATAL) << "unexpected state " << state;
+ break;
+ }
+
+ // Do the actual network I/O
+ network_moved = DoTransportIO();
+ } while ((rv != ERR_IO_PENDING || network_moved) &&
+ next_handshake_state_ != STATE_NONE);
+ return rv;
+}
+
+int SSLServerSocketNSS::DoReadLoop(int result) {
+ DCHECK(completed_handshake_);
+ DCHECK(next_handshake_state_ == STATE_NONE);
+
+ if (result < 0)
+ return result;
+
+ if (!nss_bufs_) {
+ LOG(DFATAL) << "!nss_bufs_";
+ int rv = ERR_UNEXPECTED;
+ net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
+ make_scoped_refptr(new SSLErrorParams(rv, 0)));
+ return rv;
+ }
+
+ bool network_moved;
+ int rv;
+ do {
+ rv = DoPayloadRead();
+ network_moved = DoTransportIO();
+ } while (rv == ERR_IO_PENDING && network_moved);
+ return rv;
+}
+
+int SSLServerSocketNSS::DoWriteLoop(int result) {
+ DCHECK(completed_handshake_);
+ DCHECK(next_handshake_state_ == STATE_NONE);
+
+ if (result < 0)
+ return result;
+
+ if (!nss_bufs_) {
+ LOG(DFATAL) << "!nss_bufs_";
+ int rv = ERR_UNEXPECTED;
+ net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
+ make_scoped_refptr(new SSLErrorParams(rv, 0)));
+ return rv;
+ }
+
+ bool network_moved;
+ int rv;
+ do {
+ rv = DoPayloadWrite();
+ network_moved = DoTransportIO();
+ } while (rv == ERR_IO_PENDING && network_moved);
+ return rv;
+}
+
+int SSLServerSocketNSS::DoHandshake() {
+ int net_error = net::OK;
+ SECStatus rv = SSL_ForceHandshake(nss_fd_);
+
+ if (rv == SECSuccess) {
+ completed_handshake_ = true;
+ } else {
+ PRErrorCode prerr = PR_GetError();
+ net_error = MapNSSHandshakeError(prerr);
+
+ // If not done, stay in this state
+ if (net_error == ERR_IO_PENDING) {
+ GotoState(STATE_HANDSHAKE);
+ } else {
+ LOG(ERROR) << "handshake failed; NSS error code " << prerr
+ << ", net_error " << net_error;
+ net_log_.AddEvent(
+ NetLog::TYPE_SSL_HANDSHAKE_ERROR,
+ make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
+ }
+ }
+ return net_error;
+}
+
+} // namespace net
diff --git a/net/socket/ssl_server_socket_nss.h b/net/socket/ssl_server_socket_nss.h
new file mode 100644
index 0000000..3883c9b
--- /dev/null
+++ b/net/socket/ssl_server_socket_nss.h
@@ -0,0 +1,133 @@
+// 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.
+
+#ifndef NET_SOCKET_SSL_SERVER_SOCKET_NSS_H_
+#define NET_SOCKET_SSL_SERVER_SOCKET_NSS_H_
+#pragma once
+
+#include <certt.h>
+#include <keyt.h>
+#include <nspr.h>
+#include <nss.h>
+
+#include "base/scoped_ptr.h"
+#include "net/base/completion_callback.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/net_log.h"
+#include "net/base/nss_memio.h"
+#include "net/base/ssl_config_service.h"
+#include "net/socket/ssl_server_socket.h"
+
+namespace net {
+
+class SSLServerSocketNSS : public SSLServerSocket {
+ public:
+ // This object takes ownership of the following parameters:
+ // |socket| - A socket that is already connected.
+ // |cert| - The certificate to be used by the server.
+ //
+ // The following parameters are copied in the constructor.
+ // |ssl_config| - Options for SSL socket.
+ // |key| - The private key used by the server.
+ SSLServerSocketNSS(Socket* transport_socket,
+ scoped_refptr<X509Certificate> cert,
+ base::RSAPrivateKey* key,
+ const SSLConfig& ssl_config);
+ virtual ~SSLServerSocketNSS();
+
+ // SSLServerSocket implementation.
+ virtual int Accept(CompletionCallback* callback);
+ virtual int Read(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback);
+ virtual int Write(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback);
+ virtual bool SetReceiveBufferSize(int32 size) { return false; }
+ virtual bool SetSendBufferSize(int32 size) { return false; }
+
+ private:
+ virtual int Init();
+
+ int InitializeSSLOptions();
+
+ void OnSendComplete(int result);
+ void OnRecvComplete(int result);
+ void OnHandshakeIOComplete(int result);
+
+ int BufferSend();
+ void BufferSendComplete(int result);
+ int BufferRecv();
+ void BufferRecvComplete(int result);
+ bool DoTransportIO();
+ int DoPayloadWrite();
+ int DoPayloadRead();
+
+ int DoHandshakeLoop(int last_io_result);
+ int DoReadLoop(int result);
+ int DoWriteLoop(int result);
+ int DoHandshake();
+ void DoAcceptCallback(int result);
+ void DoReadCallback(int result);
+ void DoWriteCallback(int result);
+
+ static SECStatus OwnAuthCertHandler(void* arg,
+ PRFileDesc* socket,
+ PRBool checksig,
+ PRBool is_server);
+ static void HandshakeCallback(PRFileDesc* socket, void* arg);
+
+ // Members used to send and receive buffer.
+ CompletionCallbackImpl<SSLServerSocketNSS> buffer_send_callback_;
+ CompletionCallbackImpl<SSLServerSocketNSS> buffer_recv_callback_;
+ bool transport_send_busy_;
+ bool transport_recv_busy_;
+
+ scoped_refptr<IOBuffer> recv_buffer_;
+
+ BoundNetLog net_log_;
+
+ CompletionCallback* user_accept_callback_;
+ CompletionCallback* user_read_callback_;
+ CompletionCallback* user_write_callback_;
+
+ // Used by Read function.
+ scoped_refptr<IOBuffer> user_read_buf_;
+ int user_read_buf_len_;
+
+ // Used by Write function.
+ scoped_refptr<IOBuffer> user_write_buf_;
+ int user_write_buf_len_;
+
+ // The NSS SSL state machine
+ PRFileDesc* nss_fd_;
+
+ // Buffers for the network end of the SSL state machine
+ memio_Private* nss_bufs_;
+
+ // Socket for sending and receiving data.
+ scoped_ptr<Socket> transport_socket_;
+
+ // Options for the SSL socket.
+ // TODO(hclam): This memeber is currently not used. Should make use of this
+ // member to configure the socket.
+ SSLConfig ssl_config_;
+
+ // Certificate for the server.
+ scoped_refptr<X509Certificate> cert_;
+
+ // Private key used by the server.
+ scoped_ptr<base::RSAPrivateKey> key_;
+
+ enum State {
+ STATE_NONE,
+ STATE_HANDSHAKE,
+ };
+ State next_handshake_state_;
+ bool completed_handshake_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLServerSocketNSS);
+};
+
+} // namespace net
+
+#endif // NET_SOCKET_SSL_SERVER_SOCKET_NSS_H_
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
new file mode 100644
index 0000000..781a3f4
--- /dev/null
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -0,0 +1,369 @@
+// 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.
+
+// This test suite uses SSLClientSocket to test the implementation of
+// SSLServerSocket. In order to establish connections between the sockets
+// we need two additional classes:
+// 1. FakeSocket
+// Connects SSL socket to FakeDataChannel. This class is just a stub.
+//
+// 2. FakeDataChannel
+// Implements the actual exchange of data between two FakeSockets.
+//
+// Implementations of these two classes are included in this file.
+
+#include "net/socket/ssl_server_socket.h"
+
+#include <queue>
+
+#include "base/crypto/rsa_private_key.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/nss_util.h"
+#include "base/path_service.h"
+#include "net/base/address_list.h"
+#include "net/base/cert_verifier.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/base/ssl_config_service.h"
+#include "net/base/x509_certificate.h"
+#include "net/socket/client_socket.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/socket_test_util.h"
+#include "net/socket/ssl_client_socket.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace net {
+
+namespace {
+
+class FakeDataChannel {
+ public:
+ FakeDataChannel() : read_callback_(NULL), read_buf_len_(0) {
+ }
+
+ virtual int Read(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback) {
+ if (data_.empty()) {
+ read_callback_ = callback;
+ read_buf_ = buf;
+ read_buf_len_ = buf_len;
+ return net::ERR_IO_PENDING;
+ }
+ return PropogateData(buf, buf_len);
+ }
+
+ virtual int Write(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback) {
+ data_.push(new net::DrainableIOBuffer(buf, buf_len));
+ DoReadCallback();
+ return buf_len;
+ }
+
+ private:
+ void DoReadCallback() {
+ if (!read_callback_)
+ return;
+
+ int copied = PropogateData(read_buf_, read_buf_len_);
+ net::CompletionCallback* callback = read_callback_;
+ read_callback_ = NULL;
+ read_buf_ = NULL;
+ read_buf_len_ = 0;
+ callback->Run(copied);
+ }
+
+ int PropogateData(scoped_refptr<net::IOBuffer> read_buf, int read_buf_len) {
+ scoped_refptr<net::DrainableIOBuffer> buf = data_.front();
+ int copied = std::min(buf->BytesRemaining(), read_buf_len);
+ memcpy(read_buf->data(), buf->data(), copied);
+ buf->DidConsume(copied);
+
+ if (!buf->BytesRemaining())
+ data_.pop();
+ return copied;
+ }
+
+ net::CompletionCallback* read_callback_;
+ scoped_refptr<net::IOBuffer> read_buf_;
+ int read_buf_len_;
+
+ std::queue<scoped_refptr<net::DrainableIOBuffer> > data_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeDataChannel);
+};
+
+class FakeSocket : public ClientSocket {
+ public:
+ FakeSocket(FakeDataChannel* incoming_channel,
+ FakeDataChannel* outgoing_channel)
+ : incoming_(incoming_channel),
+ outgoing_(outgoing_channel) {
+ }
+
+ virtual ~FakeSocket() {
+
+ }
+
+ virtual int Read(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback) {
+ return incoming_->Read(buf, buf_len, callback);
+ }
+
+ virtual int Write(IOBuffer* buf, int buf_len,
+ CompletionCallback* callback) {
+ return outgoing_->Write(buf, buf_len, callback);
+ }
+
+ virtual bool SetReceiveBufferSize(int32 size) {
+ return true;
+ }
+
+ virtual bool SetSendBufferSize(int32 size) {
+ return true;
+ }
+
+ virtual int Connect(CompletionCallback* callback) {
+ return net::OK;
+ }
+
+ virtual void Disconnect() {}
+
+ virtual bool IsConnected() const {
+ return true;
+ }
+
+ virtual bool IsConnectedAndIdle() const {
+ return true;
+ }
+
+ virtual int GetPeerAddress(AddressList* address) const {
+ net::IPAddressNumber ip_address(4);
+ *address = net::AddressList(ip_address, 0, false);
+ return net::OK;
+ }
+
+ virtual const BoundNetLog& NetLog() const {
+ return net_log_;
+ }
+
+ virtual void SetSubresourceSpeculation() {}
+ virtual void SetOmniboxSpeculation() {}
+
+ virtual bool WasEverUsed() const {
+ return true;
+ }
+
+ virtual bool UsingTCPFastOpen() const {
+ return false;
+ }
+
+ private:
+ net::BoundNetLog net_log_;
+ FakeDataChannel* incoming_;
+ FakeDataChannel* outgoing_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeSocket);
+};
+
+} // namespace
+
+// Verify the correctness of the test helper classes first.
+TEST(FakeSocketTest, DataTransfer) {
+ // Establish channels between two sockets.
+ FakeDataChannel channel_1;
+ FakeDataChannel channel_2;
+ FakeSocket client(&channel_1, &channel_2);
+ FakeSocket server(&channel_2, &channel_1);
+
+ const char kTestData[] = "testing123";
+ const int kTestDataSize = strlen(kTestData);
+ const int kReadBufSize = 1024;
+ scoped_refptr<net::IOBuffer> write_buf = new net::StringIOBuffer(kTestData);
+ scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(kReadBufSize);
+
+ // Write then read.
+ EXPECT_EQ(kTestDataSize, server.Write(write_buf, kTestDataSize, NULL));
+ EXPECT_EQ(kTestDataSize, client.Read(read_buf, kReadBufSize, NULL));
+ EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), kTestDataSize));
+
+ // Read then write.
+ TestCompletionCallback callback;
+ EXPECT_EQ(net::ERR_IO_PENDING,
+ server.Read(read_buf, kReadBufSize, &callback));
+ EXPECT_EQ(kTestDataSize, client.Write(write_buf, kTestDataSize, NULL));
+ EXPECT_EQ(kTestDataSize, callback.WaitForResult());
+ EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), kTestDataSize));
+}
+
+class SSLServerSocketTest : public PlatformTest {
+ public:
+ SSLServerSocketTest()
+ : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
+ }
+
+ protected:
+ void Initialize() {
+ FakeSocket* fake_client_socket = new FakeSocket(&channel_1_, &channel_2_);
+ FakeSocket* fake_server_socket = new FakeSocket(&channel_2_, &channel_1_);
+
+ FilePath certs_dir;
+ PathService::Get(base::DIR_SOURCE_ROOT, &certs_dir);
+ certs_dir = certs_dir.AppendASCII("net");
+ certs_dir = certs_dir.AppendASCII("data");
+ certs_dir = certs_dir.AppendASCII("ssl");
+ certs_dir = certs_dir.AppendASCII("certificates");
+
+ FilePath cert_path = certs_dir.AppendASCII("unittest.selfsigned.der");
+ std::string cert_der;
+ ASSERT_TRUE(file_util::ReadFileToString(cert_path, &cert_der));
+
+ scoped_refptr<net::X509Certificate> cert =
+ X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
+
+ FilePath key_path = certs_dir.AppendASCII("unittest.key.bin");
+ std::string key_string;
+ ASSERT_TRUE(file_util::ReadFileToString(key_path, &key_string));
+ std::vector<uint8> key_vector(
+ reinterpret_cast<const uint8*>(key_string.data()),
+ reinterpret_cast<const uint8*>(key_string.data() +
+ key_string.length()));
+
+ scoped_ptr<base::RSAPrivateKey> private_key(
+ base::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
+
+ net::SSLConfig ssl_config;
+ ssl_config.false_start_enabled = false;
+ ssl_config.snap_start_enabled = false;
+ ssl_config.ssl3_enabled = true;
+ ssl_config.tls1_enabled = true;
+ ssl_config.session_resume_disabled = true;
+
+ // Certificate provided by the host doesn't need authority.
+ net::SSLConfig::CertAndStatus cert_and_status;
+ cert_and_status.cert_status = net::ERR_CERT_AUTHORITY_INVALID;
+ cert_and_status.cert = cert;
+ ssl_config.allowed_bad_certs.push_back(cert_and_status);
+
+ net::HostPortPair host_and_pair("unittest", 0);
+ client_socket_.reset(
+ socket_factory_->CreateSSLClientSocket(
+ fake_client_socket, host_and_pair, ssl_config, NULL,
+ &cert_verifier_));
+ server_socket_.reset(net::CreateSSLServerSocket(fake_server_socket,
+ cert, private_key.get(),
+ net::SSLConfig()));
+ }
+
+ FakeDataChannel channel_1_;
+ FakeDataChannel channel_2_;
+ scoped_ptr<net::SSLClientSocket> client_socket_;
+ scoped_ptr<net::SSLServerSocket> server_socket_;
+ net::ClientSocketFactory* socket_factory_;
+ net::CertVerifier cert_verifier_;
+};
+
+// SSLServerSocket is only implemented using NSS.
+#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
+
+// This test only executes creation of client and server sockets. This is to
+// test that creation of sockets doesn't crash and have minimal code to run
+// under valgrind in order to help debugging memory problems.
+TEST_F(SSLServerSocketTest, Initialize) {
+ Initialize();
+}
+
+// This test executes Connect() of SSLClientSocket and Accept() of
+// SSLServerSocket to make sure handshaking between the two sockets are
+// completed successfully.
+TEST_F(SSLServerSocketTest, Handshake) {
+ Initialize();
+
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
+ TestCompletionCallback connect_callback;
+ TestCompletionCallback accept_callback;
+
+ int server_ret = server_socket_->Accept(&accept_callback);
+ EXPECT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING);
+
+ int client_ret = client_socket_->Connect(&connect_callback);
+ EXPECT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING);
+
+ if (client_ret == net::ERR_IO_PENDING) {
+ EXPECT_EQ(net::OK, connect_callback.WaitForResult());
+ }
+ if (server_ret == net::ERR_IO_PENDING) {
+ EXPECT_EQ(net::OK, accept_callback.WaitForResult());
+ }
+}
+
+TEST_F(SSLServerSocketTest, DataTransfer) {
+ Initialize();
+
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
+ TestCompletionCallback connect_callback;
+ TestCompletionCallback accept_callback;
+
+ // Establish connection.
+ int client_ret = client_socket_->Connect(&connect_callback);
+ EXPECT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING);
+
+ int server_ret = server_socket_->Accept(&accept_callback);
+ EXPECT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING);
+
+ if (client_ret == net::ERR_IO_PENDING) {
+ EXPECT_EQ(net::OK, connect_callback.WaitForResult());
+ }
+ if (server_ret == net::ERR_IO_PENDING) {
+ EXPECT_EQ(net::OK, accept_callback.WaitForResult());
+ }
+
+ const int kReadBufSize = 1024;
+ scoped_refptr<net::StringIOBuffer> write_buf =
+ new net::StringIOBuffer("testing123");
+ scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(kReadBufSize);
+
+ // Write then read.
+ TestCompletionCallback write_callback;
+ TestCompletionCallback read_callback;
+ server_ret = server_socket_->Write(write_buf, write_buf->size(),
+ &write_callback);
+ EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING);
+ client_ret = client_socket_->Read(read_buf, kReadBufSize, &read_callback);
+ EXPECT_TRUE(client_ret > 0 || client_ret == net::ERR_IO_PENDING);
+
+ if (server_ret == net::ERR_IO_PENDING) {
+ EXPECT_GT(write_callback.WaitForResult(), 0);
+ }
+ if (client_ret == net::ERR_IO_PENDING) {
+ EXPECT_GT(read_callback.WaitForResult(), 0);
+ }
+ EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size()));
+
+ // Read then write.
+ write_buf = new net::StringIOBuffer("hello123");
+ server_ret = server_socket_->Read(read_buf, kReadBufSize, &read_callback);
+ EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING);
+ client_ret = client_socket_->Write(write_buf, write_buf->size(),
+ &write_callback);
+ EXPECT_TRUE(client_ret > 0 || client_ret == net::ERR_IO_PENDING);
+
+ if (server_ret == net::ERR_IO_PENDING) {
+ EXPECT_GT(read_callback.WaitForResult(), 0);
+ }
+ if (client_ret == net::ERR_IO_PENDING) {
+ EXPECT_GT(write_callback.WaitForResult(), 0);
+ }
+ EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size()));
+}
+#endif
+
+} // namespace net
diff --git a/net/socket/tcp_client_socket_libevent.cc b/net/socket/tcp_client_socket_libevent.cc
index ccaa834..ca8b5fd 100644
--- a/net/socket/tcp_client_socket_libevent.cc
+++ b/net/socket/tcp_client_socket_libevent.cc
@@ -657,6 +657,10 @@ int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const {
return OK;
}
+const BoundNetLog& TCPClientSocketLibevent::NetLog() const {
+ return net_log_;
+}
+
void TCPClientSocketLibevent::SetSubresourceSpeculation() {
use_history_.set_subresource_speculation();
}
diff --git a/net/socket/tcp_client_socket_libevent.h b/net/socket/tcp_client_socket_libevent.h
index b5e4f55..1f3434b 100644
--- a/net/socket/tcp_client_socket_libevent.h
+++ b/net/socket/tcp_client_socket_libevent.h
@@ -49,7 +49,7 @@ class TCPClientSocketLibevent : public ClientSocket, NonThreadSafe {
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
virtual int GetPeerAddress(AddressList* address) const;
- virtual const BoundNetLog& NetLog() const { return net_log_; }
+ virtual const BoundNetLog& NetLog() const;
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
diff --git a/net/socket/tcp_client_socket_pool.cc b/net/socket/tcp_client_socket_pool.cc
index 10acc76..d490111 100644
--- a/net/socket/tcp_client_socket_pool.cc
+++ b/net/socket/tcp_client_socket_pool.cc
@@ -46,6 +46,18 @@ TCPSocketParams::TCPSocketParams(const std::string& host, int port,
TCPSocketParams::~TCPSocketParams() {}
+void TCPSocketParams::Initialize(RequestPriority priority,
+ const GURL& referrer,
+ bool disable_resolver_cache) {
+ // The referrer is used by the DNS prefetch system to correlate resolutions
+ // with the page that triggered them. It doesn't impact the actual addresses
+ // that we resolve to.
+ destination_.set_referrer(referrer);
+ destination_.set_priority(priority);
+ if (disable_resolver_cache)
+ destination_.set_allow_cached_response(false);
+}
+
// TCPConnectJobs will time out after this many seconds. Note this is the total
// time, including both host resolution and TCP connect() times.
//
@@ -284,6 +296,10 @@ void TCPClientSocketPool::CloseIdleSockets() {
base_.CloseIdleSockets();
}
+int TCPClientSocketPool::IdleSocketCount() const {
+ return base_.idle_socket_count();
+}
+
int TCPClientSocketPool::IdleSocketCountInGroup(
const std::string& group_name) const {
return base_.IdleSocketCountInGroup(group_name);
@@ -294,4 +310,19 @@ LoadState TCPClientSocketPool::GetLoadState(
return base_.GetLoadState(group_name, handle);
}
+DictionaryValue* TCPClientSocketPool::GetInfoAsValue(
+ const std::string& name,
+ const std::string& type,
+ bool include_nested_pools) const {
+ return base_.GetInfoAsValue(name, type);
+}
+
+base::TimeDelta TCPClientSocketPool::ConnectionTimeout() const {
+ return base_.ConnectionTimeout();
+}
+
+ClientSocketPoolHistograms* TCPClientSocketPool::histograms() const {
+ return base_.histograms();
+}
+
} // namespace net
diff --git a/net/socket/tcp_client_socket_pool.h b/net/socket/tcp_client_socket_pool.h
index 322e1d0..c0c7808 100644
--- a/net/socket/tcp_client_socket_pool.h
+++ b/net/socket/tcp_client_socket_pool.h
@@ -47,15 +47,7 @@ class TCPSocketParams : public base::RefCounted<TCPSocketParams> {
~TCPSocketParams();
void Initialize(RequestPriority priority, const GURL& referrer,
- bool disable_resolver_cache) {
- // The referrer is used by the DNS prefetch system to correlate resolutions
- // with the page that triggered them. It doesn't impact the actual addresses
- // that we resolve to.
- destination_.set_referrer(referrer);
- destination_.set_priority(priority);
- if (disable_resolver_cache)
- destination_.set_allow_cached_response(false);
- }
+ bool disable_resolver_cache);
HostResolver::RequestInfo destination_;
#ifdef ANDROID
@@ -158,9 +150,7 @@ class TCPClientSocketPool : public ClientSocketPool {
virtual void CloseIdleSockets();
- virtual int IdleSocketCount() const {
- return base_.idle_socket_count();
- }
+ virtual int IdleSocketCount() const;
virtual int IdleSocketCountInGroup(const std::string& group_name) const;
@@ -169,17 +159,11 @@ class TCPClientSocketPool : public ClientSocketPool {
virtual DictionaryValue* GetInfoAsValue(const std::string& name,
const std::string& type,
- bool include_nested_pools) const {
- return base_.GetInfoAsValue(name, type);
- }
+ bool include_nested_pools) const;
- virtual base::TimeDelta ConnectionTimeout() const {
- return base_.ConnectionTimeout();
- }
+ virtual base::TimeDelta ConnectionTimeout() const;
- virtual ClientSocketPoolHistograms* histograms() const {
- return base_.histograms();
- }
+ virtual ClientSocketPoolHistograms* histograms() const;
private:
typedef ClientSocketPoolBase<TCPSocketParams> PoolBase;
diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc
index c44815c..454f5b8 100644
--- a/net/socket/tcp_client_socket_pool_unittest.cc
+++ b/net/socket/tcp_client_socket_pool_unittest.cc
@@ -149,7 +149,7 @@ class MockPendingClientSocket : public ClientSocket {
virtual bool IsConnectedAndIdle() const {
return is_connected_;
}
- virtual int GetPeerAddress(AddressList* address) const{
+ virtual int GetPeerAddress(AddressList* address) const {
return ERR_UNEXPECTED;
}
virtual const BoundNetLog& NetLog() const {
@@ -251,6 +251,7 @@ class MockClientSocketFactory : public ClientSocketFactory {
const HostPortPair& host_and_port,
const SSLConfig& ssl_config,
SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
DnsCertProvenanceChecker* dns_cert_checker) {
NOTIMPLEMENTED();
delete ssl_host_info;
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc
index 64d78f3..2ed9441 100644
--- a/net/socket/tcp_client_socket_unittest.cc
+++ b/net/socket/tcp_client_socket_unittest.cc
@@ -105,10 +105,13 @@ TEST_F(TCPClientSocketTest, Connect) {
EXPECT_FALSE(sock_->IsConnected());
int rv = sock_->Connect(&callback);
+
+ net::CapturingNetLog::EntryList net_log_entries;
+ net_log_.GetEntries(&net_log_entries);
EXPECT_TRUE(net::LogContainsBeginEvent(
- net_log_.entries(), 0, net::NetLog::TYPE_SOCKET_ALIVE));
+ net_log_entries, 0, net::NetLog::TYPE_SOCKET_ALIVE));
EXPECT_TRUE(net::LogContainsBeginEvent(
- net_log_.entries(), 1, net::NetLog::TYPE_TCP_CONNECT));
+ net_log_entries, 1, net::NetLog::TYPE_TCP_CONNECT));
if (rv != OK) {
ASSERT_EQ(rv, ERR_IO_PENDING);
rv = callback.WaitForResult();
@@ -116,8 +119,9 @@ TEST_F(TCPClientSocketTest, Connect) {
}
EXPECT_TRUE(sock_->IsConnected());
+ net_log_.GetEntries(&net_log_entries);
EXPECT_TRUE(net::LogContainsEndEvent(
- net_log_.entries(), -1, net::NetLog::TYPE_TCP_CONNECT));
+ net_log_entries, -1, net::NetLog::TYPE_TCP_CONNECT));
sock_->Disconnect();
EXPECT_FALSE(sock_->IsConnected());
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc
index 4075e02..21c8e74 100644
--- a/net/socket_stream/socket_stream.cc
+++ b/net/socket_stream/socket_stream.cc
@@ -50,6 +50,8 @@ SocketStream::SocketStream(const GURL& url, Delegate* delegate)
url_(url),
max_pending_send_allowed_(kMaxPendingSendAllowed),
next_state_(STATE_NONE),
+ host_resolver_(NULL),
+ cert_verifier_(NULL),
http_auth_handler_factory_(NULL),
factory_(ClientSocketFactory::GetDefaultFactory()),
proxy_mode_(kDirectConnection),
@@ -119,6 +121,7 @@ void SocketStream::set_context(URLRequestContext* context) {
if (context_) {
host_resolver_ = context_->host_resolver();
+ cert_verifier_ = context_->cert_verifier();
http_auth_handler_factory_ = context_->http_auth_handler_factory();
}
}
@@ -800,7 +803,8 @@ int SocketStream::DoSSLConnect() {
socket_.reset(factory_->CreateSSLClientSocket(socket_.release(),
HostPortPair::FromURL(url_),
ssl_config_,
- NULL /* ssl_host_info */));
+ NULL /* ssl_host_info */,
+ cert_verifier_));
next_state_ = STATE_SSL_CONNECT_COMPLETE;
metrics_->OnSSLConnection();
return socket_->Connect(&io_callback_);
diff --git a/net/socket_stream/socket_stream.h b/net/socket_stream/socket_stream.h
index e1f2584..f485543 100644
--- a/net/socket_stream/socket_stream.h
+++ b/net/socket_stream/socket_stream.h
@@ -274,6 +274,7 @@ class SocketStream : public base::RefCountedThreadSafe<SocketStream> {
State next_state_;
HostResolver* host_resolver_;
+ CertVerifier* cert_verifier_;
HttpAuthHandlerFactory* http_auth_handler_factory_;
ClientSocketFactory* factory_;
diff --git a/net/socket_stream/socket_stream_job.cc b/net/socket_stream/socket_stream_job.cc
index 8d1da73..6636233 100644
--- a/net/socket_stream/socket_stream_job.cc
+++ b/net/socket_stream/socket_stream_job.cc
@@ -9,20 +9,17 @@
namespace net {
-static SocketStreamJobManager* GetJobManager() {
- return Singleton<SocketStreamJobManager>::get();
-}
-
// static
SocketStreamJob::ProtocolFactory* SocketStreamJob::RegisterProtocolFactory(
const std::string& scheme, ProtocolFactory* factory) {
- return GetJobManager()->RegisterProtocolFactory(scheme, factory);
+ return SocketStreamJobManager::GetInstance()->RegisterProtocolFactory(
+ scheme, factory);
}
// static
SocketStreamJob* SocketStreamJob::CreateSocketStreamJob(
const GURL& url, SocketStream::Delegate* delegate) {
- return GetJobManager()->CreateJob(url, delegate);
+ return SocketStreamJobManager::GetInstance()->CreateJob(url, delegate);
}
SocketStreamJob::SocketStreamJob() {}
diff --git a/net/socket_stream/socket_stream_job_manager.cc b/net/socket_stream/socket_stream_job_manager.cc
index 7dd0d6b..de2f0a8 100644
--- a/net/socket_stream/socket_stream_job_manager.cc
+++ b/net/socket_stream/socket_stream_job_manager.cc
@@ -4,6 +4,8 @@
#include "net/socket_stream/socket_stream_job_manager.h"
+#include "base/singleton.h"
+
namespace net {
SocketStreamJobManager::SocketStreamJobManager() {
@@ -12,6 +14,11 @@ SocketStreamJobManager::SocketStreamJobManager() {
SocketStreamJobManager::~SocketStreamJobManager() {
}
+// static
+SocketStreamJobManager* SocketStreamJobManager::GetInstance() {
+ return Singleton<SocketStreamJobManager>::get();
+}
+
SocketStreamJob* SocketStreamJobManager::CreateJob(
const GURL& url, SocketStream::Delegate* delegate) const {
// If url is invalid, create plain SocketStreamJob, which will close
diff --git a/net/socket_stream/socket_stream_job_manager.h b/net/socket_stream/socket_stream_job_manager.h
index 1150058..fbd572d 100644
--- a/net/socket_stream/socket_stream_job_manager.h
+++ b/net/socket_stream/socket_stream_job_manager.h
@@ -12,14 +12,15 @@
#include "net/socket_stream/socket_stream.h"
#include "net/socket_stream/socket_stream_job.h"
+template <typename T> struct DefaultSingletonTraits;
class GURL;
namespace net {
class SocketStreamJobManager {
public:
- SocketStreamJobManager();
- ~SocketStreamJobManager();
+ // Returns the singleton instance.
+ static SocketStreamJobManager* GetInstance();
SocketStreamJob* CreateJob(
const GURL& url, SocketStream::Delegate* delegate) const;
@@ -28,8 +29,12 @@ class SocketStreamJobManager {
const std::string& scheme, SocketStreamJob::ProtocolFactory* factory);
private:
+ friend struct DefaultSingletonTraits<SocketStreamJobManager>;
typedef std::map<std::string, SocketStreamJob::ProtocolFactory*> FactoryMap;
+ SocketStreamJobManager();
+ ~SocketStreamJobManager();
+
mutable Lock lock_;
FactoryMap factories_;
diff --git a/net/socket_stream/socket_stream_metrics_unittest.cc b/net/socket_stream/socket_stream_metrics_unittest.cc
index 64718e3..72ae142 100644
--- a/net/socket_stream/socket_stream_metrics_unittest.cc
+++ b/net/socket_stream/socket_stream_metrics_unittest.cc
@@ -15,7 +15,7 @@ using base::StatisticsRecorder;
namespace net {
TEST(SocketStreamMetricsTest, Initialize) {
- if (!StatisticsRecorder::WasStarted()) {
+ if (!StatisticsRecorder::IsActive()) {
// Create the recorder if not yet started, as SocketStreamMetrics
// relys on the StatisticsRecorder to be present. This is useful when
// tests are run with --gtest_filter='SocketStreamMetricsTest*'.
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 1b72f7c..15acff7 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -21,7 +21,8 @@
namespace net {
-SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct)
+SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session,
+ bool direct)
: ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_factory_(this)),
stream_(NULL),
spdy_session_(spdy_session),
@@ -34,6 +35,12 @@ SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct)
more_read_data_pending_(false),
direct_(direct) { }
+void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) {
+ stream_ = spdy_stream;
+ stream_->SetDelegate(this);
+ response_headers_received_ = true;
+}
+
SpdyHttpStream::~SpdyHttpStream() {
if (stream_)
stream_->DetachDelegate();
@@ -42,6 +49,7 @@ SpdyHttpStream::~SpdyHttpStream() {
int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info,
const BoundNetLog& stream_net_log,
CompletionCallback* callback) {
+ DCHECK(!stream_.get());
if (spdy_session_->IsClosed())
return ERR_CONNECTION_CLOSED;
@@ -118,7 +126,7 @@ int SpdyHttpStream::ReadResponseBody(
}
bytes_read += bytes_to_copy;
}
- if (spdy_session_->flow_control())
+ if (SpdySession::flow_control())
stream_->IncreaseRecvWindowSize(bytes_read);
return bytes_read;
} else if (stream_->closed()) {
@@ -141,6 +149,32 @@ void SpdyHttpStream::Close(bool not_reusable) {
Cancel();
}
+HttpStream* SpdyHttpStream::RenewStreamForAuth() {
+ return NULL;
+}
+
+bool SpdyHttpStream::IsResponseBodyComplete() const {
+ if (!stream_)
+ return false;
+ return stream_->closed();
+}
+
+bool SpdyHttpStream::CanFindEndOfResponse() const {
+ return true;
+}
+
+bool SpdyHttpStream::IsMoreDataBuffered() const {
+ return false;
+}
+
+bool SpdyHttpStream::IsConnectionReused() const {
+ return spdy_session_->IsReused();
+}
+
+void SpdyHttpStream::SetConnectionReused() {
+ // SPDY doesn't need an indicator here.
+}
+
int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
UploadDataStream* request_body,
HttpResponseInfo* response,
@@ -259,7 +293,10 @@ int SpdyHttpStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response,
}
response_headers_received_ = true;
- stream_->GetSSLInfo(&response_info_->ssl_info,
+ // Don't store the SSLInfo in the response here, HttpNetworkTransaction
+ // will take care of that part.
+ SSLInfo ssl_info;
+ stream_->GetSSLInfo(&ssl_info,
&response_info_->was_npn_negotiated);
response_info_->request_time = stream_->GetRequestTime();
response_info_->vary_data.Init(*request_info_, *response_info_->headers);
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index cd351cd..6e78379 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -31,10 +31,12 @@ class UploadDataStream;
// The SpdyHttpStream is a HTTP-specific type of stream known to a SpdySession.
class SpdyHttpStream : public SpdyStream::Delegate, public HttpStream {
public:
- // SpdyHttpStream constructor
SpdyHttpStream(SpdySession* spdy_session, bool direct);
virtual ~SpdyHttpStream();
+ // Initializes this SpdyHttpStream by wraping an existing SpdyStream.
+ void InitializeWithExistingStream(SpdyStream* spdy_stream);
+
SpdyStream* stream() { return stream_.get(); }
// Cancels any callbacks from being invoked and deletes the stream.
@@ -55,20 +57,12 @@ class SpdyHttpStream : public SpdyStream::Delegate, public HttpStream {
int buf_len,
CompletionCallback* callback);
virtual void Close(bool not_reusable);
- virtual HttpStream* RenewStreamForAuth() { return NULL; }
- virtual bool IsResponseBodyComplete() const {
- if (!stream_)
- return false;
- return stream_->closed();
- }
- virtual bool CanFindEndOfResponse() const { return true; }
- virtual bool IsMoreDataBuffered() const { return false; }
- virtual bool IsConnectionReused() const {
- return spdy_session_->IsReused();
- }
- virtual void SetConnectionReused() {
- // SPDY doesn't need an indicator here.
- }
+ virtual HttpStream* RenewStreamForAuth();
+ virtual bool IsResponseBodyComplete() const;
+ virtual bool CanFindEndOfResponse() const;
+ virtual bool IsMoreDataBuffered() const;
+ virtual bool IsConnectionReused() const;
+ virtual void SetConnectionReused();
virtual void GetSSLInfo(SSLInfo* ssl_info);
virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
diff --git a/net/spdy/spdy_http_utils.h b/net/spdy/spdy_http_utils.h
index c6946dd..40f0254 100644
--- a/net/spdy/spdy_http_utils.h
+++ b/net/spdy/spdy_http_utils.h
@@ -17,8 +17,8 @@ class HttpRequestHeaders;
// Convert a SpdyHeaderBlock into an HttpResponseInfo.
// |headers| input parameter with the SpdyHeaderBlock.
// |info| output parameter for the HttpResponseInfo.
-// Returns true if successfully converted. False if there was a failure
-// or if the SpdyHeaderBlock was invalid.
+// Returns true if successfully converted. False if the SpdyHeaderBlock is
+// incomplete (e.g. missing 'status' or 'version').
bool SpdyHeadersToHttpResponse(const spdy::SpdyHeaderBlock& headers,
HttpResponseInfo* response);
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 075b872..586f7dc 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -2155,7 +2155,7 @@ TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
// Send a spdy request to www.google.com that gets redirected to www.foo.com.
TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
- // These are headers which the URLRequest tacks on.
+ // These are headers which the net::URLRequest tacks on.
const char* const kExtraHeaders[] = {
"accept-charset",
"",
@@ -2233,7 +2233,7 @@ TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
HttpStreamFactory::set_force_spdy_always(true);
TestDelegate d;
{
- URLRequest r(GURL("http://www.google.com/"), &d);
+ net::URLRequest r(GURL("http://www.google.com/"), &d);
SpdyURLRequestContext* spdy_url_request_context =
new SpdyURLRequestContext();
r.set_context(spdy_url_request_context);
@@ -2265,7 +2265,7 @@ TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
// Send a spdy request to www.google.com. Get a pushed stream that redirects to
// www.foo.com.
TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
- // These are headers which the URLRequest tacks on.
+ // These are headers which the net::URLRequest tacks on.
const char* const kExtraHeaders[] = {
"accept-charset",
"",
@@ -2364,7 +2364,7 @@ TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
scoped_refptr<SpdyURLRequestContext> spdy_url_request_context(
new SpdyURLRequestContext());
{
- URLRequest r(GURL("http://www.google.com/"), &d);
+ net::URLRequest r(GURL("http://www.google.com/"), &d);
r.set_context(spdy_url_request_context);
spdy_url_request_context->socket_factory().
AddSocketDataProvider(data.get());
@@ -2376,7 +2376,7 @@ TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
std::string contents("hello!");
EXPECT_EQ(contents, d.data_received());
- URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2);
+ net::URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2);
r2.set_context(spdy_url_request_context);
spdy_url_request_context->socket_factory().
AddSocketDataProvider(data2.get());
@@ -3419,33 +3419,36 @@ TEST_P(SpdyNetworkTransactionTest, NetLog) {
// This test is intentionally non-specific about the exact ordering of the
// log; instead we just check to make sure that certain events exist, and that
// they are in the right order.
- EXPECT_LT(0u, log.entries().size());
+ net::CapturingNetLog::EntryList entries;
+ log.GetEntries(&entries);
+
+ EXPECT_LT(0u, entries.size());
int pos = 0;
- pos = net::ExpectLogContainsSomewhere(log.entries(), 0,
+ pos = net::ExpectLogContainsSomewhere(entries, 0,
net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
net::NetLog::PHASE_BEGIN);
- pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
+ pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
net::NetLog::PHASE_END);
- pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
+ pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
net::NetLog::PHASE_BEGIN);
- pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
+ pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
net::NetLog::PHASE_END);
- pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
+ pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
net::NetLog::PHASE_BEGIN);
- pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
+ pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
net::NetLog::PHASE_END);
// Check that we logged all the headers correctly
pos = net::ExpectLogContainsSomewhere(
- log.entries(), 0,
+ entries, 0,
net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
net::NetLog::PHASE_NONE);
- CapturingNetLog::Entry entry = log.entries()[pos];
+ CapturingNetLog::Entry entry = entries[pos];
NetLogSpdySynParameter* request_params =
static_cast<NetLogSpdySynParameter*>(entry.extra_parameters.get());
spdy::SpdyHeaderBlock* headers =
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index 62816d2..6d743d2 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -59,6 +59,11 @@ SpdyProxyClientSocket::~SpdyProxyClientSocket() {
Disconnect();
}
+HttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() {
+ DCHECK(response_stream_.get());
+ return response_stream_.release();
+}
+
// Sends a SYN_STREAM frame to the proxy with a CONNECT request
// for the specified endpoint. Waits for the server to send back
// a SYN_REPLY frame. OK will be returned if the status is 200.
@@ -116,6 +121,10 @@ bool SpdyProxyClientSocket::IsConnectedAndIdle() const {
return IsConnected() && !spdy_stream_->is_idle();
}
+const BoundNetLog& SpdyProxyClientSocket::NetLog() const {
+ return net_log_;
+}
+
void SpdyProxyClientSocket::SetSubresourceSpeculation() {
// TODO(rch): what should this implementation be?
}
@@ -361,10 +370,22 @@ int SpdyProxyClientSocket::DoReadReplyComplete(int result) {
make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
}
- if (response_.headers->response_code() == 200)
+ if (response_.headers->response_code() == 200) {
return OK;
- else
+ } else if (response_.headers->response_code() == 407) {
return ERR_TUNNEL_CONNECTION_FAILED;
+ } else {
+ // Immediately hand off our SpdyStream to a newly created SpdyHttpStream
+ // so that any subsequent SpdyFrames are processed in the context of
+ // the HttpStream, not the socket.
+ DCHECK(spdy_stream_);
+ SpdyStream* stream = spdy_stream_;
+ spdy_stream_ = NULL;
+ response_stream_.reset(new SpdyHttpStream(NULL, false));
+ response_stream_->InitializeWithExistingStream(stream);
+ next_state_ = STATE_DISCONNECTED;
+ return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
+ }
}
// SpdyStream::Delegate methods:
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
index 213cac4..64bcd6a 100644
--- a/net/spdy/spdy_proxy_client_socket.h
+++ b/net/spdy/spdy_proxy_client_socket.h
@@ -18,7 +18,8 @@
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_info.h"
-#include "net/socket/client_socket.h"
+#include "net/http/proxy_client_socket.h"
+#include "net/spdy/spdy_http_stream.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_stream.h"
@@ -35,7 +36,8 @@ class IOBuffer;
class SpdySession;
class SpdyStream;
-class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
+class SpdyProxyClientSocket : public ProxyClientSocket,
+ public SpdyStream::Delegate {
public:
// Create a socket on top of the |spdy_stream| by sending a SYN_STREAM
// CONNECT frame for |endpoint|. After the SYN_REPLY is received,
@@ -57,10 +59,17 @@ class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
return auth_;
}
- const HttpResponseInfo* GetConnectResponseInfo() const {
+ // ProxyClientSocket methods:
+
+ virtual const HttpResponseInfo* GetConnectResponseInfo() const {
return response_.headers ? &response_ : NULL;
}
+ // In the event of a non-200 response to the CONNECT request, this
+ // method may be called to return an HttpStream in order to read
+ // the response body.
+ virtual HttpStream* CreateConnectResponseStream();
+
// ClientSocket methods:
#ifdef ANDROID
virtual int Connect(CompletionCallback* callback, bool wait_for_connect);
@@ -70,7 +79,7 @@ class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
- virtual const BoundNetLog& NetLog() const { return net_log_; }
+ virtual const BoundNetLog& NetLog() const;
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
@@ -156,6 +165,8 @@ class SpdyProxyClientSocket : public ClientSocket, public SpdyStream::Delegate {
// True if the transport socket has ever sent data.
bool was_ever_used_;
+ scoped_ptr<SpdyHttpStream> response_stream_;
+
const BoundNetLog net_log_;
DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocket);
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc
index 236713a..c4c5f2c 100644
--- a/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -839,12 +839,14 @@ TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
Initialize(reads, arraysize(reads), writes, arraysize(writes));
- AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
+ AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
Run(2); // SpdySession consumes the next two reads and sends then to
// sock_ to be buffered.
- AssertSyncReadEquals(kMsg1, kLen1);
- AssertSyncReadEquals(kMsg2, kLen2);
+ EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->Read(NULL, 1, NULL));
+ scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1 + kLen2));
+ scoped_ptr<HttpStream> stream(sock_->CreateConnectResponseStream());
+ stream->ReadResponseBody(buf, kLen1 + kLen2, &read_callback_);
}
// ----------- Reads and Writes
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 225c159..cbc1365 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -8,6 +8,7 @@
#include "base/linked_ptr.h"
#include "base/logging.h"
#include "base/message_loop.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/stats_counters.h"
#include "base/stl_util-inl.h"
#include "base/string_number_conversions.h"
@@ -62,17 +63,6 @@ namespace {
const int kReadBufferSize = 8 * 1024;
-void AdjustSocketBufferSizes(ClientSocket* socket) {
- // Adjust socket buffer sizes.
- // SPDY uses one socket, and we want a really big buffer.
- // This greatly helps on links with packet loss - we can even
- // outperform Vista's dynamic window sizing algorithm.
- // TODO(mbelshe): more study.
- const int kSocketBufferSize = 512 * 1024;
- socket->SetReceiveBufferSize(kSocketBufferSize);
- socket->SetSendBufferSize(kSocketBufferSize);
-}
-
class NetLogSpdySessionParameter : public NetLog::EventParameters {
public:
NetLogSpdySessionParameter(const HostPortProxyPair& host_pair)
@@ -246,8 +236,10 @@ SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair,
streams_pushed_and_claimed_count_(0),
streams_abandoned_count_(0),
frames_received_(0),
+ bytes_received_(0),
sent_settings_(false),
received_settings_(false),
+ stalled_streams_(0),
initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize),
initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize),
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)) {
@@ -293,8 +285,6 @@ net::Error SpdySession::InitializeWithSocket(
static base::StatsCounter spdy_sessions("spdy.sessions");
spdy_sessions.Increment();
- AdjustSocketBufferSizes(connection->socket());
-
state_ = CONNECTED;
connection_.reset(connection);
is_secure_ = is_secure;
@@ -346,6 +336,7 @@ int SpdySession::CreateStream(
return CreateStreamImpl(url, priority, spdy_stream, stream_net_log);
}
+ stalled_streams_++;
net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS, NULL);
create_stream_queues_[priority].push(
PendingCreateStream(url, priority, spdy_stream,
@@ -595,6 +586,8 @@ void SpdySession::OnReadComplete(int bytes_read) {
return;
}
+ bytes_received_ += bytes_read;
+
// The SpdyFramer will use callbacks onto |this| as it parses frames.
// When errors occur, those callbacks can lead to teardown of all references
// to |this|, so maintain a reference to self during this call for safe
@@ -945,9 +938,7 @@ scoped_refptr<SpdyStream> SpdySession::GetActivePushStream(
used_push_streams.Increment();
return stream;
}
- else {
- return NULL;
- }
+ return NULL;
}
bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, bool* was_npn_negotiated) {
@@ -1334,10 +1325,53 @@ void SpdySession::SendWindowUpdate(spdy::SpdyStreamId stream_id,
QueueFrame(window_update_frame.get(), stream->priority(), stream);
}
+// Given a cwnd that we would have sent to the server, modify it based on the
+// field trial policy.
+uint32 ApplyCwndFieldTrialPolicy(int cwnd) {
+ base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd");
+ if (trial->group_name() == "cwnd32")
+ return 32;
+ else if (trial->group_name() == "cwnd16")
+ return 16;
+ else if (trial->group_name() == "cwndMin16")
+ return std::max(cwnd, 16);
+ else if (trial->group_name() == "cwndMin10")
+ return std::max(cwnd, 10);
+ else if (trial->group_name() == "cwndDynamic")
+ return cwnd;
+ NOTREACHED();
+ return cwnd;
+}
+
void SpdySession::SendSettings() {
- const spdy::SpdySettings& settings = spdy_settings_->Get(host_port_pair());
+ // Note: we're copying the settings here, so that we can potentially modify
+ // the settings for the field trial. When removing the field trial, make
+ // this a reference to the const SpdySettings again.
+ spdy::SpdySettings settings = spdy_settings_->Get(host_port_pair());
if (settings.empty())
return;
+
+ // Record Histogram Data and Apply the SpdyCwnd FieldTrial if applicable.
+ for (spdy::SpdySettings::iterator i = settings.begin(),
+ end = settings.end(); i != end; ++i) {
+ const uint32 id = i->first.id();
+ const uint32 val = i->second;
+ switch (id) {
+ case spdy::SETTINGS_CURRENT_CWND:
+ uint32 cwnd = 0;
+ cwnd = ApplyCwndFieldTrialPolicy(val);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent",
+ cwnd,
+ 1, 200, 100);
+ if (cwnd != val) {
+ i->second = cwnd;
+ i->first.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
+ spdy_settings_->Set(host_port_pair(), settings);
+ }
+ break;
+ }
+ }
+
HandleSettings(settings);
net_log_.AddEvent(
@@ -1383,6 +1417,11 @@ void SpdySession::RecordHistograms() {
sent_settings_ ? 1 : 0, 2);
UMA_HISTOGRAM_ENUMERATION("Net.SpdySettingsReceived",
received_settings_ ? 1 : 0, 2);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamStallsPerSession",
+ stalled_streams_,
+ 0, 300, 50);
+ UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionsWithStalls",
+ stalled_streams_ > 0 ? 1 : 0, 2);
if (received_settings_) {
// Enumerate the saved settings, and set histograms for it.
@@ -1393,9 +1432,31 @@ void SpdySession::RecordHistograms() {
const spdy::SpdySetting setting = *it;
switch (setting.first.id()) {
case spdy::SETTINGS_CURRENT_CWND:
+ // Record several different histograms to see if cwnd converges
+ // for larger volumes of data being sent.
UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd",
setting.second,
1, 200, 100);
+ if (bytes_received_ > 10 * 1024) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd10K",
+ setting.second,
+ 1, 200, 100);
+ if (bytes_received_ > 25 * 1024) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd25K",
+ setting.second,
+ 1, 200, 100);
+ if (bytes_received_ > 50 * 1024) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd50K",
+ setting.second,
+ 1, 200, 100);
+ if (bytes_received_ > 100 * 1024) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd100K",
+ setting.second,
+ 1, 200, 100);
+ }
+ }
+ }
+ }
break;
case spdy::SETTINGS_ROUND_TRIP_TIME:
UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRTT",
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 210e9af..6268a4f 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -207,7 +207,7 @@ class SpdySession : public base::RefCounted<SpdySession>,
CLOSED
};
- enum { kDefaultMaxConcurrentStreams = 6 }; // TODO(mbelshe) remove this
+ enum { kDefaultMaxConcurrentStreams = 10 };
struct PendingCreateStream {
const GURL* url;
@@ -408,9 +408,11 @@ class SpdySession : public base::RefCounted<SpdySession>,
int streams_pushed_and_claimed_count_;
int streams_abandoned_count_;
int frames_received_;
+ int bytes_received_;
bool sent_settings_; // Did this session send settings when it started.
bool received_settings_; // Did this session receive at least one settings
// frame.
+ int stalled_streams_; // Count of streams that were ever stalled.
// Initial send window size for the session; can be changed by an
// arriving SETTINGS frame; newly created streams use this value for the
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index 8a5d4a4..3900993 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "base/message_loop.h"
-#include "base/singleton.h"
#include "base/values.h"
#include "net/spdy/spdy_session.h"
@@ -47,7 +46,6 @@ SpdyStream::SpdyStream(SpdySession* session,
send_window_size_(spdy::kSpdyStreamInitialWindowSize),
recv_window_size_(spdy::kSpdyStreamInitialWindowSize),
pushed_(pushed),
- metrics_(Singleton<BandwidthMetrics>::get()),
response_received_(false),
session_(session),
delegate_(NULL),
diff --git a/net/spdy/spdy_test_util.h b/net/spdy/spdy_test_util.h
index 0a5d2e0..aeabe6a 100644
--- a/net/spdy/spdy_test_util.h
+++ b/net/spdy/spdy_test_util.h
@@ -7,6 +7,7 @@
#pragma once
#include "base/basictypes.h"
+#include "net/base/cert_verifier.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/request_priority.h"
#include "net/base/ssl_config_service_defaults.h"
@@ -327,6 +328,7 @@ class SpdySessionDependencies {
// Default set of dependencies -- "null" proxy service.
SpdySessionDependencies()
: host_resolver(new MockHostResolver),
+ cert_verifier(new CertVerifier),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
socket_factory(new MockClientSocketFactory),
@@ -345,6 +347,7 @@ class SpdySessionDependencies {
// Custom proxy service dependency.
explicit SpdySessionDependencies(ProxyService* proxy_service)
: host_resolver(new MockHostResolver),
+ cert_verifier(new CertVerifier),
proxy_service(proxy_service),
ssl_config_service(new SSLConfigServiceDefaults),
socket_factory(new MockClientSocketFactory),
@@ -354,6 +357,7 @@ class SpdySessionDependencies {
// NOTE: host_resolver must be ordered before http_auth_handler_factory.
scoped_ptr<MockHostResolverBase> host_resolver;
+ scoped_ptr<CertVerifier> cert_verifier;
scoped_refptr<ProxyService> proxy_service;
scoped_refptr<SSLConfigService> ssl_config_service;
scoped_ptr<MockClientSocketFactory> socket_factory;
@@ -363,6 +367,7 @@ class SpdySessionDependencies {
static HttpNetworkSession* SpdyCreateSession(
SpdySessionDependencies* session_deps) {
return new HttpNetworkSession(session_deps->host_resolver.get(),
+ session_deps->cert_verifier.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -377,6 +382,7 @@ class SpdySessionDependencies {
static HttpNetworkSession* SpdyCreateSessionDeterministic(
SpdySessionDependencies* session_deps) {
return new HttpNetworkSession(session_deps->host_resolver.get(),
+ session_deps->cert_verifier.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -395,6 +401,7 @@ class SpdyURLRequestContext : public URLRequestContext {
public:
SpdyURLRequestContext() {
host_resolver_ = new MockHostResolver();
+ cert_verifier_ = new CertVerifier;
proxy_service_ = ProxyService::CreateDirect();
ssl_config_service_ = new SSLConfigServiceDefaults;
http_auth_handler_factory_ = HttpAuthHandlerFactory::CreateDefault(
@@ -402,6 +409,7 @@ class SpdyURLRequestContext : public URLRequestContext {
http_transaction_factory_ = new net::HttpCache(
new HttpNetworkLayer(&socket_factory_,
host_resolver_,
+ cert_verifier_,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -420,6 +428,7 @@ class SpdyURLRequestContext : public URLRequestContext {
virtual ~SpdyURLRequestContext() {
delete http_transaction_factory_;
delete http_auth_handler_factory_;
+ delete cert_verifier_;
delete host_resolver_;
}
diff --git a/net/test/test_server.cc b/net/test/test_server.cc
index 0eaf8b5..9722dc1 100644
--- a/net/test/test_server.cc
+++ b/net/test/test_server.cc
@@ -26,10 +26,10 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "googleurl/src/gurl.h"
-#include "net/base/cert_test_util.h"
#include "net/base/host_port_pair.h"
#include "net/base/host_resolver.h"
#include "net/base/test_completion_callback.h"
+#include "net/base/test_root_certs.h"
#include "net/socket/tcp_client_socket.h"
#include "net/test/python_utils.h"
#include "testing/platform_test.h"
@@ -58,10 +58,6 @@ std::string GetHostname(TestServer::Type type,
} // namespace
-#if defined(OS_MACOSX)
-void SetMacTestCertificate(X509Certificate* cert);
-#endif
-
TestServer::HTTPSOptions::HTTPSOptions()
: server_certificate(CERT_OK),
request_client_certificate(false),
@@ -103,9 +99,8 @@ TestServer::TestServer(const HTTPSOptions& https_options,
}
TestServer::~TestServer() {
-#if defined(OS_MACOSX)
- SetMacTestCertificate(NULL);
-#endif
+ TestRootCerts* root_certs = TestRootCerts::GetInstance();
+ root_certs->Clear();
Stop();
}
@@ -132,8 +127,6 @@ bool TestServer::Start() {
if (type_ == TYPE_HTTPS) {
if (!LoadTestRootCert())
return false;
- if (!CheckCATrusted())
- return false;
}
// Get path to python server script
@@ -159,6 +152,8 @@ bool TestServer::Start() {
return false;
}
+ allowed_port_.reset(new ScopedPortException(host_port_pair_.port()));
+
started_ = true;
return true;
}
@@ -181,6 +176,8 @@ bool TestServer::Stop() {
VLOG(1) << "Kill failed?";
}
+ allowed_port_.reset();
+
return ret;
}
@@ -314,27 +311,8 @@ FilePath TestServer::GetRootCertificatePath() {
}
bool TestServer::LoadTestRootCert() {
-#if defined(USE_NSS)
- if (cert_)
- return true;
-
- // TODO(dkegel): figure out how to get this to only happen once?
-
- // This currently leaks a little memory.
- // TODO(dkegel): fix the leak and remove the entry in
- // tools/valgrind/memcheck/suppressions.txt
- ANNOTATE_SCOPED_MEMORY_LEAK; // Tell heap checker about the leak.
- cert_ = LoadTemporaryRootCert(GetRootCertificatePath());
- return (cert_ != NULL);
-#elif defined(OS_MACOSX)
- X509Certificate* cert = LoadTemporaryRootCert(GetRootCertificatePath());
- if (!cert)
- return false;
- SetMacTestCertificate(cert);
- return true;
-#else
- return true;
-#endif
+ TestRootCerts* root_certs = TestRootCerts::GetInstance();
+ return root_certs->AddFromFile(GetRootCertificatePath());
}
bool TestServer::AddCommandLineArguments(CommandLine* command_line) const {
diff --git a/net/test/test_server.h b/net/test/test_server.h
index 00a8fc9..9686aef 100644
--- a/net/test/test_server.h
+++ b/net/test/test_server.h
@@ -17,16 +17,12 @@
#include "base/file_util.h"
#include "base/process_util.h"
#include "net/base/host_port_pair.h"
+#include "net/base/net_util.h"
#if defined(OS_WIN)
#include "base/scoped_handle_win.h"
#endif
-#if defined(USE_NSS)
-#include "base/ref_counted.h"
-#include "net/base/x509_certificate.h"
-#endif
-
class CommandLine;
class DictionaryValue;
class GURL;
@@ -155,9 +151,6 @@ class TestServer {
// Returns path to the root certificate.
FilePath GetRootCertificatePath();
- // Returns false if our test root certificate is not trusted.
- bool CheckCATrusted() WARN_UNUSED_RESULT;
-
// Load the test root cert, if it hasn't been loaded yet.
bool LoadTestRootCert() WARN_UNUSED_RESULT;
@@ -180,6 +173,8 @@ class TestServer {
// Handle of the Python process running the test server.
base::ProcessHandle process_handle_;
+ scoped_ptr<net::ScopedPortException> allowed_port_;
+
#if defined(OS_WIN)
// JobObject used to clean up orphaned child processes.
ScopedHandle job_handle_;
@@ -200,10 +195,6 @@ class TestServer {
// 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
-
Type type_;
// Has the server been started?
diff --git a/net/test/test_server_posix.cc b/net/test/test_server_posix.cc
index 43bdb10..de42fb3 100644
--- a/net/test/test_server_posix.cc
+++ b/net/test/test_server_posix.cc
@@ -118,7 +118,7 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
// Try to kill any orphaned testserver processes that may be running.
OrphanedTestServerFilter filter(testserver_path.value(),
base::IntToString(host_port_pair_.port()));
- if (!base::KillProcesses(L"python", -1, &filter)) {
+ if (!base::KillProcesses("python", -1, &filter)) {
LOG(WARNING) << "Failed to clean up older orphaned testserver instances.";
}
@@ -163,8 +163,4 @@ bool TestServer::WaitToStart() {
return true;
}
-bool TestServer::CheckCATrusted() {
- return true;
-}
-
} // namespace net
diff --git a/net/test/test_server_win.cc b/net/test/test_server_win.cc
index e1c54e9..e38d0bc 100644
--- a/net/test/test_server_win.cc
+++ b/net/test/test_server_win.cc
@@ -216,32 +216,4 @@ bool TestServer::WaitToStart() {
return true;
}
-bool TestServer::CheckCATrusted() {
- HCERTSTORE cert_store = CertOpenSystemStore(NULL, L"ROOT");
- if (!cert_store) {
- LOG(ERROR) << " could not open trusted root CA store";
- return false;
- }
- PCCERT_CONTEXT cert =
- CertFindCertificateInStore(cert_store,
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- 0,
- CERT_FIND_ISSUER_STR,
- L"Test CA",
- NULL);
- if (cert)
- CertFreeCertificateContext(cert);
- CertCloseStore(cert_store, 0);
-
- if (!cert) {
- LOG(ERROR) << " TEST CONFIGURATION ERROR: you need to import the test ca "
- "certificate to your trusted roots for this test to work. "
- "For more info visit:\n"
- "http://dev.chromium.org/developers/testing\n";
- return false;
- }
-
- return true;
-}
-
} // namespace net
diff --git a/net/tools/dump_cache/dump_cache.cc b/net/tools/dump_cache/dump_cache.cc
index 9644aae..3561fb7 100644
--- a/net/tools/dump_cache/dump_cache.cc
+++ b/net/tools/dump_cache/dump_cache.cc
@@ -46,16 +46,16 @@ const char kInputPath[] = "input";
const char kOutputPath[] = "output";
// Dumps the file headers to stdout.
-const wchar_t kDumpHeaders[] = L"dump-headers";
+const char kDumpHeaders[] = "dump-headers";
// Dumps all entries to stdout.
-const wchar_t kDumpContents[] = L"dump-contents";
+const char kDumpContents[] = "dump-contents";
// Convert the cache to files.
-const wchar_t kDumpToFiles[] = L"dump-to-files";
+const char kDumpToFiles[] = "dump-to-files";
// Upgrade an old version to the current one.
-const wchar_t kUpgrade[] = L"upgrade";
+const char kUpgrade[] = "upgrade";
// Internal use:
const char kSlave[] = "slave";
diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc
index 138bed3..0d9682f 100644
--- a/net/tools/fetch/fetch_client.cc
+++ b/net/tools/fetch/fetch_client.cc
@@ -6,11 +6,12 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/metrics/stats_counters.h"
-#include "base/singleton.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
+#include "net/base/cert_verifier.h"
#include "net/base/completion_callback.h"
#include "net/base/host_resolver.h"
#include "net/base/io_buffer.h"
@@ -47,6 +48,8 @@ class Driver {
int clients_;
};
+static base::LazyInstance<Driver> g_driver(base::LINKER_INITIALIZED);
+
// A network client
class Client {
public:
@@ -60,7 +63,7 @@ class Client {
int rv = factory->CreateTransaction(&transaction_);
DCHECK_EQ(net::OK, rv);
buffer_->AddRef();
- driver_->ClientStarted();
+ g_driver.Get().ClientStarted();
request_info_.url = url_;
request_info_.method = "GET";
int state = transaction_->Start(
@@ -101,7 +104,7 @@ class Client {
void OnRequestComplete(int result) {
static base::StatsCounter requests("FetchClient.requests");
requests.Increment();
- driver_->ClientStopped();
+ g_driver.Get().ClientStopped();
printf(".");
}
@@ -112,7 +115,6 @@ class Client {
scoped_refptr<net::IOBuffer> buffer_;
net::CompletionCallbackImpl<Client> connect_callback_;
net::CompletionCallbackImpl<Client> read_callback_;
- Singleton<Driver> driver_;
};
int main(int argc, char**argv) {
@@ -139,6 +141,7 @@ int main(int argc, char**argv) {
net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
NULL, NULL));
+ scoped_ptr<net::CertVerifier> cert_verifier(new net::CertVerifier);
scoped_refptr<net::ProxyService> proxy_service(
net::ProxyService::CreateDirect());
scoped_refptr<net::SSLConfigService> ssl_config_service(
@@ -147,13 +150,15 @@ int main(int argc, char**argv) {
scoped_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory(
net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
if (use_cache) {
- factory = new net::HttpCache(host_resolver.get(), NULL, NULL, proxy_service,
- ssl_config_service, http_auth_handler_factory.get(), NULL, NULL,
+ factory = new net::HttpCache(host_resolver.get(), cert_verifier.get(),
+ NULL, NULL, proxy_service, ssl_config_service,
+ http_auth_handler_factory.get(), NULL, NULL,
net::HttpCache::DefaultBackend::InMemory(0));
} else {
factory = new net::HttpNetworkLayer(
net::ClientSocketFactory::GetDefaultFactory(),
host_resolver.get(),
+ cert_verifier.get(),
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -203,7 +208,7 @@ int main(int argc, char**argv) {
// Dump the stats table.
printf("<stats>\n");
int counter_max = table.GetMaxCounters();
- for (int index=0; index < counter_max; index++) {
+ for (int index = 0; index < counter_max; index++) {
std::string name(table.GetRowName(index));
if (name.length() > 0) {
int value = table.GetRowValue(index);
diff --git a/net/tools/flip_server/balsa_headers.h b/net/tools/flip_server/balsa_headers.h
index a33e857..b51b7f4 100644
--- a/net/tools/flip_server/balsa_headers.h
+++ b/net/tools/flip_server/balsa_headers.h
@@ -392,12 +392,12 @@ class BalsaHeaders {
};
typedef std::vector<base::StringPiece> HeaderTokenList;
- friend bool net::ParseHTTPFirstLine(const char* begin,
- const char* end,
- bool is_request,
- size_t max_request_uri_length,
- BalsaHeaders* headers,
- BalsaFrameEnums::ErrorCode* error_code);
+ friend bool ParseHTTPFirstLine(const char* begin,
+ const char* end,
+ bool is_request,
+ size_t max_request_uri_length,
+ BalsaHeaders* headers,
+ BalsaFrameEnums::ErrorCode* error_code);
protected:
typedef std::vector<HeaderLineDescription> HeaderLines;
@@ -502,16 +502,14 @@ class BalsaHeaders {
const HeaderLines::size_type original_idx = idx_;
do {
--idx_;
- } while (idx_ >= 0 &&
- idx_ < header_lines_size &&
- header_lines[idx_].skip == true);
+ } while (idx_ < header_lines_size && header_lines[idx_].skip == true);
// The condition below exists so that --(rbegin() + 1) == rbegin(), even
// if there are only 'skip == true' elements between the rbegin() iterator
// and the beginning of the vector of HeaderLineDescriptions.
// TODO(fenix): refactor this list so that we don't have to do
// linear scanning through skipped headers (and this condition is
// then unnecessary)
- if (idx_ < 0 || idx_ > header_lines_size) {
+ if (idx_ > header_lines_size) {
idx_ = original_idx - 1;
}
}
@@ -1279,4 +1277,3 @@ class BalsaHeaders {
} // namespace net
#endif // NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_H_
-
diff --git a/net/tools/flip_server/flip_config.h b/net/tools/flip_server/flip_config.h
index 3f202f8..fdf0f46 100644
--- a/net/tools/flip_server/flip_config.h
+++ b/net/tools/flip_server/flip_config.h
@@ -30,8 +30,11 @@ public:
string listen_port_;
string ssl_cert_filename_;
string ssl_key_filename_;
- string server_ip_;
- string server_port_;
+ string http_server_ip_;
+ string http_server_port_;
+ string https_server_ip_;
+ string https_server_port_;
+ int spdy_only_;
int accept_backlog_size_;
bool disable_nagle_;
int accepts_per_wake_;
@@ -43,8 +46,11 @@ public:
string listen_port,
string ssl_cert_filename,
string ssl_key_filename,
- string server_ip,
- string server_port,
+ string http_server_ip,
+ string http_server_port,
+ string https_server_ip,
+ string https_server_port,
+ int spdy_only,
int accept_backlog_size,
bool disable_nagle,
int accepts_per_wake,
@@ -56,8 +62,11 @@ public:
listen_port_(listen_port),
ssl_cert_filename_(ssl_cert_filename),
ssl_key_filename_(ssl_key_filename),
- server_ip_(server_ip),
- server_port_(server_port),
+ http_server_ip_(http_server_ip),
+ http_server_port_(http_server_port),
+ https_server_ip_(https_server_ip),
+ https_server_port_(https_server_port),
+ spdy_only_(spdy_only),
accept_backlog_size_(accept_backlog_size),
disable_nagle_(disable_nagle),
accepts_per_wake_(accepts_per_wake),
@@ -65,6 +74,11 @@ public:
{
VLOG(1) << "Attempting to listen on " << listen_ip_.c_str() << ":"
<< listen_port_.c_str();
+ if (!https_server_ip_.size())
+ https_server_ip_ = http_server_ip_;
+ if (!https_server_port_.size())
+ https_server_port_ = http_server_port_;
+
while (1) {
int ret = net::CreateListeningSocket(listen_ip_,
listen_port_,
@@ -89,8 +103,24 @@ public:
}
}
net::SetNonBlocking(listen_fd_);
- VLOG(1) << "Listening for spdy on port: " << listen_ip_ << ":"
- << listen_port_;
+ VLOG(1) << "Listening on socket: ";
+ if (flip_handler_type == FLIP_HANDLER_PROXY)
+ VLOG(1) << "\tType : Proxy";
+ else if (FLIP_HANDLER_SPDY_SERVER)
+ VLOG(1) << "\tType : SPDY Server";
+ else if (FLIP_HANDLER_HTTP_SERVER)
+ VLOG(1) << "\tType : HTTP Server";
+ VLOG(1) << "\tIP : " << listen_ip_;
+ VLOG(1) << "\tPort : " << listen_port_;
+ VLOG(1) << "\tHTTP Server : " << http_server_ip_ << ":"
+ << http_server_port_;
+ VLOG(1) << "\tHTTPS Server : " << https_server_ip_ << ":"
+ << https_server_port_;
+ VLOG(1) << "\tSSL : "
+ << (ssl_cert_filename.size()?"true":"false");
+ VLOG(1) << "\tCertificate : " << ssl_cert_filename;
+ VLOG(1) << "\tKey : " << ssl_key_filename;
+ VLOG(1) << "\tSpdy Only : " << (spdy_only?"true":"flase");
}
~FlipAcceptor () {}
};
@@ -105,13 +135,15 @@ public:
string forward_ip_header_;
bool wait_for_iface_;
int ssl_session_expiry_;
+ bool ssl_disable_compression_;
FlipConfig() :
server_think_time_in_s_(0),
log_destination_(logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG),
forward_ip_header_enabled_(false),
wait_for_iface_(false),
- ssl_session_expiry_(300)
+ ssl_session_expiry_(300),
+ ssl_disable_compression_(false)
{}
~FlipConfig() {}
@@ -121,8 +153,11 @@ public:
string listen_port,
string ssl_cert_filename,
string ssl_key_filename,
- string server_ip,
- string server_port,
+ string http_server_ip,
+ string http_server_port,
+ string https_server_ip,
+ string https_server_port,
+ int spdy_only,
int accept_backlog_size,
bool disable_nagle,
int accepts_per_wake,
@@ -135,8 +170,11 @@ public:
listen_port,
ssl_cert_filename,
ssl_key_filename,
- server_ip,
- server_port,
+ http_server_ip,
+ http_server_port,
+ https_server_ip,
+ https_server_port,
+ spdy_only,
accept_backlog_size,
disable_nagle,
accepts_per_wake,
diff --git a/net/tools/flip_server/flip_in_mem_edsm_server.cc b/net/tools/flip_server/flip_in_mem_edsm_server.cc
index 7848861..1969e0c 100644
--- a/net/tools/flip_server/flip_in_mem_edsm_server.cc
+++ b/net/tools/flip_server/flip_in_mem_edsm_server.cc
@@ -56,12 +56,10 @@ using std::cout;
#define ACCEPTOR_CLIENT_IDENT acceptor_->listen_ip_ << ":" \
<< acceptor_->listen_port_ << " "
-#define ACCEPTOR_SERVER_IDENT acceptor_->server_ip_ << ":" \
- << acceptor_->server_port_ << " "
#define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0"
-#define SSL_CTX_DEFAULT_CIPHER_LIST "RC4:!aNULL:!eNULL"
+#define SSL_CTX_DEFAULT_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH"
// If true, then disables the nagle algorithm);
bool FLAGS_disable_nagle = true;
@@ -214,7 +212,8 @@ void spdy_init_ssl(SSLState* state,
LOG(FATAL) << "Unable to create SSL context";
}
// Disable SSLv2 support.
- SSL_CTX_set_options(state->ssl_ctx, SSL_OP_NO_SSLv2);
+ SSL_CTX_set_options(state->ssl_ctx,
+ SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE);
if (SSL_CTX_use_certificate_file(state->ssl_ctx,
ssl_cert_name.c_str(),
SSL_FILETYPE_PEM) <= 0) {
@@ -246,6 +245,17 @@ void spdy_init_ssl(SSLState* state,
VLOG(1) << "SSL CTX: Setting Release Buffers mode.";
SSL_CTX_set_mode(state->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
+
+ // Proper methods to disable compression don't exist until 0.9.9+. For now
+ // we must manipulate the stack of compression methods directly.
+ if (g_proxy_config.ssl_disable_compression_) {
+ STACK_OF(SSL_COMP) *ssl_comp_methods = SSL_COMP_get_compression_methods();
+ int num_methods = sk_SSL_COMP_num(ssl_comp_methods);
+ int i;
+ for (i = 0; i < num_methods; i++) {
+ static_cast<void>(sk_SSL_COMP_delete(ssl_comp_methods, i));
+ }
+ }
}
SSL* spdy_new_ssl(SSL_CTX* ssl_ctx) {
@@ -680,6 +690,8 @@ class SMInterface {
SMInterface* sm_interface,
EpollServer* epoll_server,
int fd,
+ string server_ip,
+ string server_port,
bool use_ssl) = 0;
virtual size_t ProcessReadInput(const char* data, size_t len) = 0;
virtual size_t ProcessWriteInput(const char* data, size_t len) = 0;
@@ -810,6 +822,9 @@ class SMConnection: public SMConnectionInterface,
SSL* ssl_;
public:
+ string server_ip_;
+ string server_port_;
+
EpollServer* epoll_server() { return epoll_server_; }
OutputList* output_list() { return &output_list_; }
MemoryCache* memory_cache() { return memory_cache_; }
@@ -848,6 +863,8 @@ class SMConnection: public SMConnectionInterface,
SMInterface* sm_interface,
EpollServer* epoll_server,
int fd,
+ string server_ip,
+ string server_port,
bool use_ssl) {
if (initialized_) {
LOG(FATAL) << "Attempted to initialize already initialized server";
@@ -862,9 +879,11 @@ class SMConnection: public SMConnectionInterface,
// 0 == connection in progress
// 1 == connection complete
// TODO: is_numeric_host_address value needs to be detected
+ server_ip_ = server_ip;
+ server_port_ = server_port;
int ret = net::CreateConnectedSocket(&fd_,
- acceptor_->server_ip_,
- acceptor_->server_port_,
+ server_ip,
+ server_port,
true,
acceptor_->disable_nagle_);
@@ -875,10 +894,12 @@ class SMConnection: public SMConnectionInterface,
DCHECK_NE(-1, fd_);
connection_complete_ = true;
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << "Connection complete to: " << ACCEPTOR_SERVER_IDENT;
+ << "Connection complete to: " << server_ip_ << ":"
+ << server_port_ << " ";
}
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << "Connecting to server: " << ACCEPTOR_SERVER_IDENT;
+ << "Connecting to server: " << server_ip_ << ":"
+ << server_port_ << " ";
} else {
// If fd != -1 then we are initializing a connection that has just been
// accepted from the listen socket.
@@ -932,24 +953,40 @@ class SMConnection: public SMConnectionInterface,
}
}
- int Send(const char* bytes, int len, int flags) {
+ int Send(const char* data, int len, int flags) {
ssize_t bytes_written = 0;
if (ssl_) {
- bytes_written = SSL_write(ssl_, bytes, len);
- if (bytes_written < 0) {
- switch(SSL_get_error(ssl_, bytes_written)) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_ACCEPT:
- case SSL_ERROR_WANT_CONNECT:
- return -2;
- default:
- PrintSslError();
- break;
+ // Write smallish chunks to SSL so that we don't have large
+ // multi-packet TLS records to receive before being able to handle
+ // the data.
+ while(len > 0) {
+ const int kMaxTLSRecordSize = 1460;
+ const char* ptr = &(data[bytes_written]);
+ int chunksize = std::min(len, kMaxTLSRecordSize);
+ int rv = SSL_write(ssl_, ptr, chunksize);
+ if (rv <= 0) {
+ switch(SSL_get_error(ssl_, rv)) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_ACCEPT:
+ case SSL_ERROR_WANT_CONNECT:
+ rv = -2;
+ break;
+ default:
+ PrintSslError();
+ break;
+ }
+ // If we wrote some data, return that count. Otherwise
+ // return the stall error.
+ return bytes_written > 0 ? bytes_written : rv;
}
+ bytes_written += rv;
+ len -= rv;
+ if (rv != chunksize)
+ break; // If we couldn't write everything, we're implicitly stalled
}
} else {
- bytes_written = send(fd_, bytes, len, flags);
+ bytes_written = send(fd_, data, len, flags);
}
return bytes_written;
}
@@ -1014,7 +1051,8 @@ class SMConnection: public SMConnectionInterface,
if (sock_error == 0) {
connection_complete_ = true;
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << "Connection complete to " << ACCEPTOR_SERVER_IDENT;
+ << "Connection complete to " << server_ip_ << ":"
+ << server_port_ << " ";
} else if (sock_error == EINPROGRESS) {
return;
} else {
@@ -1137,6 +1175,10 @@ class SMConnection: public SMConnectionInterface,
<< "Reusing SPDY interface.";
}
sm_interface_ = sm_spdy_interface_;
+ } else if (acceptor_->spdy_only_) {
+ VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
+ << "SPDY proxy only, closing HTTPS connection.";
+ goto error_or_close;
} else {
if (!sm_streamer_interface_) {
sm_streamer_interface_ = NewStreamerSM(this, NULL,
@@ -1582,11 +1624,14 @@ class SpdySM : public SpdyFramerVisitorInterface, public SMInterface {
SMInterface* sm_interface,
EpollServer* epoll_server,
int fd,
+ string server_ip,
+ string server_port,
bool use_ssl) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT
<< "SpdySM: Initializing server connection.";
connection_->InitSMConnection(connection_pool, sm_interface,
- epoll_server, fd, use_ssl);
+ epoll_server, fd, server_ip, server_port,
+ use_ssl);
}
private:
@@ -1610,7 +1655,8 @@ class SpdySM : public SpdyFramerVisitorInterface, public SMInterface {
return sm_http_interface;
}
- SMInterface* FindOrMakeNewSMConnectionInterface() {
+ SMInterface* FindOrMakeNewSMConnectionInterface(string server_ip,
+ string server_port) {
SMInterface *sm_http_interface;
int32 server_idx;
if (unused_server_interface_list.empty()) {
@@ -1630,19 +1676,22 @@ class SpdySM : public SpdyFramerVisitorInterface, public SMInterface {
sm_http_interface->InitSMInterface(this, server_idx);
sm_http_interface->InitSMConnection(NULL, sm_http_interface,
- epoll_server_, -1, false);
+ epoll_server_, -1,
+ server_ip, server_port, false);
return sm_http_interface;
}
- int SpdyHandleNewStream(const SpdyControlFrame* frame,
- string *http_data)
+ int SpdyHandleNewStream(const SpdyControlFrame* frame,
+ string *http_data,
+ bool *is_https_scheme)
{
bool parsed_headers = false;
SpdyHeaderBlock headers;
const SpdySynStreamControlFrame* syn_stream =
reinterpret_cast<const SpdySynStreamControlFrame*>(frame);
+ *is_https_scheme = false;
parsed_headers = spdy_framer_->ParseHeaderBlock(frame, &headers);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSyn("
<< syn_stream->stream_id() << ")";
@@ -1660,6 +1709,11 @@ class SpdySM : public SpdyFramerVisitorInterface, public SMInterface {
return 0;
}
+ SpdyHeaderBlock::iterator scheme = headers.find("scheme");
+ if (scheme->second.compare("https") == 0) {
+ *is_https_scheme = true;
+ }
+
string uri = UrlUtilities::GetUrlPath(url->second);
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) {
SpdyHeaderBlock::iterator referer = headers.find("referer");
@@ -1707,15 +1761,25 @@ class SpdySM : public SpdyFramerVisitorInterface, public SMInterface {
reinterpret_cast<const SpdySynStreamControlFrame*>(frame);
string http_data;
- int ret = SpdyHandleNewStream(frame, &http_data);
+ bool is_https_scheme;
+ int ret = SpdyHandleNewStream(frame, &http_data, &is_https_scheme);
if (!ret) {
LOG(ERROR) << "SpdySM: Could not convert spdy into http.";
break;
}
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
+ string server_ip;
+ string server_port;
+ if (is_https_scheme) {
+ server_ip = acceptor_->https_server_ip_;
+ server_port = acceptor_->https_server_port_;
+ } else {
+ server_ip = acceptor_->http_server_ip_;
+ server_port = acceptor_->http_server_port_;
+ }
SMInterface *sm_http_interface =
- FindOrMakeNewSMConnectionInterface();
+ FindOrMakeNewSMConnectionInterface(server_ip, server_port);
stream_to_smif_[syn_stream->stream_id()] = sm_http_interface;
sm_http_interface->SetStreamID(syn_stream->stream_id());
sm_http_interface->ProcessWriteInput(http_data.c_str(),
@@ -2151,7 +2215,8 @@ class HttpSM : public BalsaVisitorInterface, public SMInterface {
stream_id_ += 2;
} else {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Received Response from "
- << ACCEPTOR_SERVER_IDENT;
+ << connection_->server_ip_ << ":"
+ << connection_->server_port_ << " ";
sm_spdy_interface_->SendSynReply(stream_id_, headers);
}
}
@@ -2175,9 +2240,9 @@ class HttpSM : public BalsaVisitorInterface, public SMInterface {
virtual void ProcessChunkExtensions(const char *input, size_t size) {}
virtual void HeaderDone() {}
virtual void MessageDone() {
+ if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone. Sending EOF: "
<< "stream " << stream_id_;
- if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
sm_spdy_interface_->SendEOF(stream_id_);
} else {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone.";
@@ -2215,12 +2280,15 @@ class HttpSM : public BalsaVisitorInterface, public SMInterface {
SMInterface* sm_interface,
EpollServer* epoll_server,
int fd,
+ string server_ip,
+ string server_port,
bool use_ssl)
{
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Initializing server "
<< "connection.";
connection_->InitSMConnection(connection_pool, sm_interface,
- epoll_server, fd, use_ssl);
+ epoll_server, fd, server_ip, server_port,
+ use_ssl);
}
size_t ProcessReadInput(const char* data, size_t len) {
@@ -2259,7 +2327,7 @@ class HttpSM : public BalsaVisitorInterface, public SMInterface {
}
void Reset() {
- VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream %d "
+ VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream "
<< stream_id_;
http_framer_->Reset();
}
@@ -2268,8 +2336,11 @@ class HttpSM : public BalsaVisitorInterface, public SMInterface {
}
void ResetForNewConnection() {
- VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing "
- << "to: " << ACCEPTOR_SERVER_IDENT;
+ if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
+ VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing "
+ << "to: " << connection_->server_ip_ << ":"
+ << connection_->server_port_ << " ";
+ }
seq_num_ = 0;
output_ordering_.Reset();
http_framer_->Reset();
@@ -2495,12 +2566,15 @@ class StreamerSM : public SMInterface {
SMInterface* sm_interface,
EpollServer* epoll_server,
int fd,
+ string server_ip,
+ string server_port,
bool use_ssl)
{
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Initializing server "
<< "connection.";
connection_->InitSMConnection(connection_pool, sm_interface,
- epoll_server, fd, use_ssl);
+ epoll_server, fd, server_ip,
+ server_port, use_ssl);
}
size_t ProcessReadInput(const char* data, size_t len) {
@@ -2562,8 +2636,13 @@ class StreamerSM : public SMInterface {
epoll_server_, acceptor_);
sm_other_interface_->InitSMInterface(this, 0);
}
+ // The Streamer interface is used to stream HTTPS connections, so we
+ // will always use the https_server_ip/port here.
sm_other_interface_->InitSMConnection(NULL, sm_other_interface_,
- epoll_server_, -1, false);
+ epoll_server_, -1,
+ acceptor_->https_server_ip_,
+ acceptor_->https_server_port_,
+ false);
return 1;
}
@@ -2734,6 +2813,7 @@ class SMAcceptorThread : public SimpleThread,
NULL,
&epoll_server_,
server_fd,
+ "", "",
use_ssl_);
}
@@ -2883,22 +2963,43 @@ int main (int argc, char**argv)
unsigned int i = 0;
bool wait_for_iface = false;
+ signal(SIGPIPE, SIG_IGN);
+
CommandLine::Init(argc, argv);
CommandLine cl(argc, argv);
- if (cl.HasSwitch("--help") || argc < 2) {
+ if (cl.HasSwitch("help") || argc < 2) {
cout << argv[0] << " <options>\n";
- cout << "\t--proxy<1..n>=\"<listen ip>,<listen port>,<ssl cert filename>,"
- << "<ssl key filename>,<server ip>,<server port>\"\n";
- cout << "\t--spdy-server=\"<listen ip>,<listen port>,<ssl cert filename>,"
- << "<ssl key filename>\"\n";
- cout << "\t--http-server=\"<listen ip>,<listen port>,<ssl cert filename>,"
- << "<ssl key filename>\"\n";
+ cout << " Proxy options:\n";
+ cout << "\t--proxy<1..n>=\"<listen ip>,<listen port>,"
+ << "<ssl cert filename>,\n"
+ << "\t <ssl key filename>,<http server ip>,"
+ << "<http server port>,\n"
+ << "\t [https server ip],[https server port],"
+ << "<spdy only 0|1>\"\n";
+ cout << "\t * The https server ip and port may be left empty if they are"
+ << " the same as\n"
+ << "\t the http server fields.\n";
+ cout << "\t * spdy only prevents non-spdy https connections from being"
+ << " passed\n"
+ << "\t through the proxy listen ip:port.\n";
cout << "\t--forward-ip-header=<header name>\n";
- cout << "\t--logdest=file|system|both\n";
+ cout << "\n Server options:\n";
+ cout << "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],\n"
+ << "\t [ssl key filename]\"\n";
+ cout << "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],\n"
+ << "\t [ssl key filename]\"\n";
+ cout << "\t * Leaving the ssl cert and key fields empty will disable ssl"
+ << " for the\n"
+ << "\t http and spdy flip servers\n";
+ cout << "\n Global options:\n";
+ cout << "\t--logdest=<file|system|both>\n";
cout << "\t--logfile=<logfile>\n";
cout << "\t--wait-for-iface\n";
+ cout << "\t * The flip server will block until the listen ip has been"
+ << " raised.\n";
cout << "\t--ssl-session-expiry=<seconds> (default is 300)\n";
+ cout << "\t--ssl-disable-compression\n";
cout << "\t--help\n";
exit(0);
}
@@ -2949,23 +3050,31 @@ int main (int argc, char**argv)
g_proxy_config.ssl_session_expiry_ = atoi( session_expiry.c_str() );
}
+ if (cl.HasSwitch("ssl-disable-compression")) {
+ g_proxy_config.ssl_disable_compression_ = true;
+ }
+
InitLogging(g_proxy_config.log_filename_.c_str(),
g_proxy_config.log_destination_,
logging::DONT_LOCK_LOG_FILE,
logging::APPEND_TO_OLD_LOG_FILE);
LOG(INFO) << "Flip SPDY proxy started with configuration:";
- LOG(INFO) << "Logging destination : " << g_proxy_config.log_destination_;
- LOG(INFO) << "Log file : " << g_proxy_config.log_filename_;
- LOG(INFO) << "Forward IP Header : "
+ LOG(INFO) << "Logging destination : " << g_proxy_config.log_destination_;
+ LOG(INFO) << "Log file : " << g_proxy_config.log_filename_;
+ LOG(INFO) << "Forward IP Header : "
<< (g_proxy_config.forward_ip_header_enabled_ ?
g_proxy_config.forward_ip_header_ : "(disabled)");
- LOG(INFO) << "Wait for interfaces : " << (wait_for_iface?"true":"false");
- LOG(INFO) << "Accept backlog size : " << FLAGS_accept_backlog_size;
- LOG(INFO) << "Accepts per wake : " << FLAGS_accepts_per_wake;
- LOG(INFO) << "Disable nagle : "
+ LOG(INFO) << "Wait for interfaces : " << (wait_for_iface?"true":"false");
+ LOG(INFO) << "Accept backlog size : " << FLAGS_accept_backlog_size;
+ LOG(INFO) << "Accepts per wake : " << FLAGS_accepts_per_wake;
+ LOG(INFO) << "Disable nagle : "
<< (FLAGS_disable_nagle?"true":"false");
- LOG(INFO) << "Reuseport : " << (FLAGS_reuseport?"true":"false");
+ LOG(INFO) << "Reuseport : " << (FLAGS_reuseport?"true":"false");
+ LOG(INFO) << "SSL session expiry : "
+ << g_proxy_config.ssl_session_expiry_;
+ LOG(INFO) << "SSL disable compression : "
+ << g_proxy_config.ssl_disable_compression_;
// Proxy Acceptors
while (true) {
@@ -2977,13 +3086,16 @@ int main (int argc, char**argv)
}
string value = cl.GetSwitchValueASCII(name.str());
vector<std::string> valueArgs = split(value, ',');
- CHECK_EQ((unsigned int)6, valueArgs.size());
+ CHECK_EQ((unsigned int)9, valueArgs.size());
+ int spdy_only = atoi(valueArgs[8].c_str());
// If wait_for_iface is enabled, then this call will block
// indefinitely until the interface is raised.
g_proxy_config.AddAcceptor(FLIP_HANDLER_PROXY,
valueArgs[0], valueArgs[1],
valueArgs[2], valueArgs[3],
valueArgs[4], valueArgs[5],
+ valueArgs[6], valueArgs[7],
+ spdy_only,
FLAGS_accept_backlog_size,
FLAGS_disable_nagle,
FLAGS_accepts_per_wake,
@@ -3001,7 +3113,8 @@ int main (int argc, char**argv)
g_proxy_config.AddAcceptor(FLIP_HANDLER_SPDY_SERVER,
valueArgs[0], valueArgs[1],
valueArgs[2], valueArgs[3],
- "", "",
+ "", "", "", "",
+ 0,
FLAGS_accept_backlog_size,
FLAGS_disable_nagle,
FLAGS_accepts_per_wake,
@@ -3019,7 +3132,8 @@ int main (int argc, char**argv)
g_proxy_config.AddAcceptor(FLIP_HANDLER_HTTP_SERVER,
valueArgs[0], valueArgs[1],
valueArgs[2], valueArgs[3],
- "", "",
+ "", "", "", "",
+ 0,
FLAGS_accept_backlog_size,
FLAGS_disable_nagle,
FLAGS_accepts_per_wake,
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index c0dc930..56d7c0e 100755
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -151,17 +151,22 @@ class SyncHTTPServer(StoppableHTTPServer):
"""This is a merge of asyncore.loop() and SocketServer.serve_forever().
"""
- def RunDispatcherHandler(dispatcher, handler):
- """Handles a single event for an asyncore.dispatcher.
+ def HandleXmppSocket(fd, socket_map, handler):
+ """Runs the handler for the xmpp connection for fd.
Adapted from asyncore.read() et al.
"""
+ xmpp_connection = socket_map.get(fd)
+ # This could happen if a previous handler call caused fd to get
+ # removed from socket_map.
+ if xmpp_connection is None:
+ return
try:
- handler(dispatcher)
+ handler(xmpp_connection)
except (asyncore.ExitNow, KeyboardInterrupt, SystemExit):
raise
except:
- dispatcher.handle_error()
+ xmpp_connection.handle_error()
while True:
read_fds = [ self.fileno() ]
@@ -191,19 +196,16 @@ class SyncHTTPServer(StoppableHTTPServer):
if fd == self.fileno():
self.HandleRequestNoBlock()
continue
- xmpp_connection = self._xmpp_socket_map.get(fd)
- RunDispatcherHandler(xmpp_connection,
- asyncore.dispatcher.handle_read_event)
+ HandleXmppSocket(fd, self._xmpp_socket_map,
+ asyncore.dispatcher.handle_read_event)
for fd in write_fds:
- xmpp_connection = self._xmpp_socket_map.get(fd)
- RunDispatcherHandler(xmpp_connection,
- asyncore.dispatcher.handle_write_event)
+ HandleXmppSocket(fd, self._xmpp_socket_map,
+ asyncore.dispatcher.handle_write_event)
for fd in exceptional_fds:
- xmpp_connection = self._xmpp_socket_map.get(fd)
- RunDispatcherHandler(xmpp_connection,
- asyncore.dispatcher.handle_expt_event)
+ HandleXmppSocket(fd, self._xmpp_socket_map,
+ asyncore.dispatcher.handle_expt_event)
class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
@@ -302,11 +304,12 @@ class TestPageHandler(BasePageHandler):
self._mime_types = {
'crx' : 'application/x-chrome-extension',
+ 'exe' : 'application/octet-stream',
'gif': 'image/gif',
'jpeg' : 'image/jpeg',
'jpg' : 'image/jpeg',
- 'xml' : 'text/xml',
- 'pdf' : 'application/pdf'
+ 'pdf' : 'application/pdf',
+ 'xml' : 'text/xml'
}
self._default_mime_type = 'text/html'
diff --git a/net/tools/testserver/xmppserver.py b/net/tools/testserver/xmppserver.py
index ac9c276..de93076 100644
--- a/net/tools/testserver/xmppserver.py
+++ b/net/tools/testserver/xmppserver.py
@@ -370,23 +370,29 @@ class XmppConnection(asynchat.async_chat):
</iq>
""")
- def __init__(self, sock, socket_map, connections, addr):
+ def __init__(self, sock, socket_map, delegate, 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.
+ delegate: The delegate, which is notified when the XMPP
+ handshake is successful, when the connection is closed, and
+ when a notification has to be broadcast.
addr: The host/port of the client.
"""
- asynchat.async_chat.__init__(self, sock)
+ # We do this because in versions of python < 2.6,
+ # async_chat.__init__ doesn't take a map argument nor pass it to
+ # dispatcher.__init__. We rely on the fact that
+ # async_chat.__init__ calls dispatcher.__init__ as the last thing
+ # it does, and that calling dispatcher.__init__ with socket=None
+ # and map=None is essentially a no-op.
+ asynchat.async_chat.__init__(self)
+ asyncore.dispatcher.__init__(self, sock, socket_map)
+
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._delegate = delegate
self._parser = StanzaParser(self)
self._jid = None
@@ -412,11 +418,10 @@ class XmppConnection(asynchat.async_chat):
def found_terminator(self):
asynchat.async_chat.found_terminator(self)
- def handle_close(self):
+ def 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()]
+ self._delegate.OnXmppConnectionClosed(self)
+ asynchat.async_chat.close(self)
# Called by self._parser.FeedString().
def FeedStanza(self, stanza):
@@ -431,7 +436,7 @@ class XmppConnection(asynchat.async_chat):
def HandshakeDone(self, jid):
self._jid = jid
self._handshake_task = None
- self._connections.add(self)
+ self._delegate.OnXmppHandshakeDone(self)
print "Handshake done for %s" % self
def _HandleIq(self, iq):
@@ -454,7 +459,7 @@ class XmppConnection(asynchat.async_chat):
self._SendNotifierStanza(id, 'result')
elif command == 'set':
# Send notification request.
- SendNotification(self._connections)
+ self._delegate.SendNotification(self)
else:
raise UnexpectedXml(command_xml)
@@ -491,13 +496,6 @@ class XmppConnection(asynchat.async_chat):
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.
@@ -518,9 +516,30 @@ class XmppServer(asyncore.dispatcher):
self.bind(addr)
self.listen(5)
self._socket_map = socket_map
- self._socket_map[self.fileno()] = self
self._connections = set()
+ self._handshake_done_connections = set()
def handle_accept(self):
(sock, addr) = self.accept()
- XmppConnection(sock, self._socket_map, self._connections, addr)
+ xmpp_connection = XmppConnection(sock, self._socket_map, self, addr)
+ self._connections.add(xmpp_connection)
+
+ def close(self):
+ # A copy is necessary since calling close on each connection
+ # removes it from self._connections.
+ for connection in self._connections.copy():
+ connection.close()
+ asyncore.dispatcher.close(self)
+
+ # XmppConnection delegate methods.
+ def OnXmppHandshakeDone(self, xmpp_connection):
+ self._handshake_done_connections.add(xmpp_connection)
+
+ def OnXmppConnectionClosed(self, xmpp_connection):
+ self._connections.discard(xmpp_connection)
+ self._handshake_done_connections.discard(xmpp_connection)
+
+ def SendNotification(self, unused_xmpp_connection):
+ for connection in self._handshake_done_connections:
+ print 'Sending notification to %s' % connection
+ connection.SendNotification()
diff --git a/net/tools/testserver/xmppserver_test.py b/net/tools/testserver/xmppserver_test.py
index e033a69..61a996f 100644
--- a/net/tools/testserver/xmppserver_test.py
+++ b/net/tools/testserver/xmppserver_test.py
@@ -168,6 +168,7 @@ class HandshakeTaskTest(unittest.TestCase):
class XmppConnectionTest(unittest.TestCase):
def setUp(self):
+ self.connections = set()
self.data = []
# socket-like methods.
@@ -184,13 +185,29 @@ class XmppConnectionTest(unittest.TestCase):
self.data.append(data)
pass
+ def close(self):
+ pass
+
+ # XmppConnection delegate methods.
+ def OnXmppHandshakeDone(self, xmpp_connection):
+ self.connections.add(xmpp_connection)
+
+ def OnXmppConnectionClosed(self, xmpp_connection):
+ self.connections.discard(xmpp_connection)
+
+ def SendNotification(self, unused_xmpp_connection):
+ for connection in self.connections:
+ connection.SendNotification()
+
def testBasic(self):
- connections = set()
+ socket_map = {}
xmpp_connection = xmppserver.XmppConnection(
- self, {}, connections, ('', 0))
- self.assertEqual(len(connections), 0)
+ self, socket_map, self, ('', 0))
+ self.assertEqual(len(socket_map), 1)
+ self.assertEqual(len(self.connections), 0)
xmpp_connection.HandshakeDone(xmppserver.Jid('foo', 'bar'))
- self.assertEqual(len(connections), 1)
+ self.assertEqual(len(socket_map), 1)
+ self.assertEqual(len(self.connections), 1)
# Test subscription request.
self.assertEqual(len(self.data), 0)
@@ -220,6 +237,10 @@ class XmppConnectionTest(unittest.TestCase):
self.assertRaises(xmppserver.UnexpectedXml,
SendUnexpectedNotifierCommand)
+ # Test close
+ xmpp_connection.close()
+ self.assertEqual(len(socket_map), 0)
+ self.assertEqual(len(self.connections), 0)
class XmppServerTest(unittest.TestCase):
@@ -233,6 +254,9 @@ class XmppServerTest(unittest.TestCase):
def getpeername(self):
return ('', 0)
+ def close(self):
+ pass
+
def testBasic(self):
class FakeXmppServer(xmppserver.XmppServer):
def accept(self2):
@@ -244,6 +268,8 @@ class XmppServerTest(unittest.TestCase):
self.assertEqual(len(socket_map), 1)
xmpp_server.handle_accept()
self.assertEqual(len(socket_map), 2)
+ xmpp_server.close()
+ self.assertEqual(len(socket_map), 0)
if __name__ == '__main__':
diff --git a/net/url_request/https_prober.cc b/net/url_request/https_prober.cc
index d69eaf3..bdafcf6 100644
--- a/net/url_request/https_prober.cc
+++ b/net/url_request/https_prober.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/singleton.h"
#include "net/url_request/https_prober.h"
#include "net/url_request/url_request.h"
@@ -15,6 +16,11 @@ HTTPSProber::HTTPSProber() {
HTTPSProber::~HTTPSProber() {
}
+// static
+HTTPSProber* HTTPSProber::GetInstance() {
+ return Singleton<HTTPSProber>::get();
+}
+
bool HTTPSProber::HaveProbed(const std::string& host) const {
return probed_.find(host) != probed_.end();
}
@@ -34,21 +40,21 @@ bool HTTPSProber::ProbeHost(const std::string& host, URLRequestContext* ctx,
GURL url("https://" + host);
DCHECK_EQ(url.host(), host);
- URLRequest* req = new URLRequest(url, this);
+ net::URLRequest* req = new net::URLRequest(url, this);
req->set_context(ctx);
req->Start();
return true;
}
-void HTTPSProber::Success(URLRequest* request) {
+void HTTPSProber::Success(net::URLRequest* request) {
DoCallback(request, true);
}
-void HTTPSProber::Failure(URLRequest* request) {
+void HTTPSProber::Failure(net::URLRequest* request) {
DoCallback(request, false);
}
-void HTTPSProber::DoCallback(URLRequest* request, bool result) {
+void HTTPSProber::DoCallback(net::URLRequest* request, bool result) {
std::map<std::string, HTTPSProberDelegate*>::iterator i =
inflight_probes_.find(request->original_url().host());
DCHECK(i != inflight_probes_.end());
@@ -60,18 +66,18 @@ void HTTPSProber::DoCallback(URLRequest* request, bool result) {
delegate->ProbeComplete(result);
}
-void HTTPSProber::OnAuthRequired(URLRequest* request,
+void HTTPSProber::OnAuthRequired(net::URLRequest* request,
net::AuthChallengeInfo* auth_info) {
Success(request);
}
-void HTTPSProber::OnSSLCertificateError(URLRequest* request,
+void HTTPSProber::OnSSLCertificateError(net::URLRequest* request,
int cert_error,
net::X509Certificate* cert) {
request->ContinueDespiteLastError();
}
-void HTTPSProber::OnResponseStarted(URLRequest* request) {
+void HTTPSProber::OnResponseStarted(net::URLRequest* request) {
if (request->status().status() == URLRequestStatus::SUCCESS) {
Success(request);
} else {
@@ -79,7 +85,7 @@ void HTTPSProber::OnResponseStarted(URLRequest* request) {
}
}
-void HTTPSProber::OnReadCompleted(URLRequest* request, int bytes_read) {
+void HTTPSProber::OnReadCompleted(net::URLRequest* request, int bytes_read) {
NOTREACHED();
}
diff --git a/net/url_request/https_prober.h b/net/url_request/https_prober.h
index 28182c4..5d1a622 100644
--- a/net/url_request/https_prober.h
+++ b/net/url_request/https_prober.h
@@ -10,17 +10,17 @@
#include <set>
#include <string>
-#include "base/singleton.h"
#include "base/task.h"
#include "net/url_request/url_request.h"
+template <typename T> struct DefaultSingletonTraits;
class URLRequestContext;
namespace net {
// This should be scoped inside HTTPSProber, but VC cannot compile
// HTTPProber::Delegate when HTTPSProber also inherits from
-// URLRequest::Delegate.
+// net::URLRequest::Delegate.
class HTTPSProberDelegate {
public:
virtual void ProbeComplete(bool result) = 0;
@@ -31,10 +31,10 @@ class HTTPSProberDelegate {
// HTTPSProber is a singleton object that manages HTTPS probes. A HTTPS probe
// determines if we can connect to a given host over HTTPS. It's used when
// transparently upgrading from HTTP to HTTPS (for example, for SPDY).
-class HTTPSProber : public URLRequest::Delegate {
+class HTTPSProber : public net::URLRequest::Delegate {
public:
- HTTPSProber();
- ~HTTPSProber();
+ // Returns the singleton instance.
+ static HTTPSProber* GetInstance();
// HaveProbed returns true if the given host is known to have been probed
// since the browser was last started.
@@ -52,19 +52,22 @@ class HTTPSProber : public URLRequest::Delegate {
bool ProbeHost(const std::string& host, URLRequestContext* ctx,
HTTPSProberDelegate* delegate);
- // Implementation of URLRequest::Delegate
- void OnAuthRequired(URLRequest* request,
- net::AuthChallengeInfo* auth_info);
- void OnSSLCertificateError(URLRequest* request,
- int cert_error,
- net::X509Certificate* cert);
- void OnResponseStarted(URLRequest* request);
- void OnReadCompleted(URLRequest* request, int bytes_read);
+ // Implementation of net::URLRequest::Delegate
+ virtual void OnAuthRequired(net::URLRequest* request,
+ net::AuthChallengeInfo* auth_info);
+ virtual void OnSSLCertificateError(net::URLRequest* request,
+ int cert_error,
+ net::X509Certificate* cert);
+ virtual void OnResponseStarted(net::URLRequest* request);
+ virtual void OnReadCompleted(net::URLRequest* request, int bytes_read);
private:
- void Success(URLRequest* request);
- void Failure(URLRequest* request);
- void DoCallback(URLRequest* request, bool result);
+ HTTPSProber();
+ ~HTTPSProber();
+
+ void Success(net::URLRequest* request);
+ void Failure(net::URLRequest* request);
+ void DoCallback(net::URLRequest* request, bool result);
std::map<std::string, HTTPSProberDelegate*> inflight_probes_;
std::set<std::string> probed_;
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index ac54a1f..26a9da2 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -29,10 +29,6 @@ namespace {
// Max number of http redirects to follow. Same number as gecko.
const int kMaxRedirects = 20;
-URLRequestJobManager* GetJobManager() {
- return Singleton<URLRequestJobManager>::get();
-}
-
// Discard headers which have meaning in POST (Content-Length, Content-Type,
// Origin).
void StripPostSpecificHeaders(net::HttpRequestHeaders* headers) {
@@ -44,6 +40,8 @@ void StripPostSpecificHeaders(net::HttpRequestHeaders* headers) {
} // namespace
+namespace net {
+
///////////////////////////////////////////////////////////////////////////////
// URLRequest::Interceptor
@@ -128,17 +126,19 @@ URLRequest::~URLRequest() {
// static
URLRequest::ProtocolFactory* URLRequest::RegisterProtocolFactory(
const string& scheme, ProtocolFactory* factory) {
- return GetJobManager()->RegisterProtocolFactory(scheme, factory);
+ return URLRequestJobManager::GetInstance()->RegisterProtocolFactory(scheme,
+ factory);
}
// static
void URLRequest::RegisterRequestInterceptor(Interceptor* interceptor) {
- GetJobManager()->RegisterRequestInterceptor(interceptor);
+ URLRequestJobManager::GetInstance()->RegisterRequestInterceptor(interceptor);
}
// static
void URLRequest::UnregisterRequestInterceptor(Interceptor* interceptor) {
- GetJobManager()->UnregisterRequestInterceptor(interceptor);
+ URLRequestJobManager::GetInstance()->UnregisterRequestInterceptor(
+ interceptor);
}
void URLRequest::AppendBytesToUpload(const char* bytes, int bytes_len) {
@@ -262,7 +262,7 @@ int URLRequest::GetResponseCode() {
// static
bool URLRequest::IsHandledProtocol(const std::string& scheme) {
- return GetJobManager()->SupportsScheme(scheme);
+ return URLRequestJobManager::GetInstance()->SupportsScheme(scheme);
}
// static
@@ -277,12 +277,12 @@ bool URLRequest::IsHandledURL(const GURL& url) {
// static
void URLRequest::AllowFileAccess() {
- GetJobManager()->set_enable_file_access(true);
+ URLRequestJobManager::GetInstance()->set_enable_file_access(true);
}
// static
bool URLRequest::IsFileAccessAllowed() {
- return GetJobManager()->enable_file_access();
+ return URLRequestJobManager::GetInstance()->enable_file_access();
}
@@ -316,7 +316,7 @@ GURL URLRequest::GetSanitizedReferrer() const {
}
void URLRequest::Start() {
- StartJob(GetJobManager()->CreateJob(this));
+ StartJob(URLRequestJobManager::GetInstance()->CreateJob(this));
}
///////////////////////////////////////////////////////////////////////////////
@@ -351,7 +351,7 @@ void URLRequest::StartJob(URLRequestJob* job) {
void URLRequest::Restart() {
// Should only be called if the original job didn't make any progress.
DCHECK(job_ && !job_->has_response_started());
- RestartWithJob(GetJobManager()->CreateJob(this));
+ RestartWithJob(URLRequestJobManager::GetInstance()->CreateJob(this));
}
void URLRequest::RestartWithJob(URLRequestJob *job) {
@@ -425,7 +425,9 @@ void URLRequest::StopCaching() {
}
void URLRequest::ReceivedRedirect(const GURL& location, bool* defer_redirect) {
- URLRequestJob* job = GetJobManager()->MaybeInterceptRedirect(this, location);
+ URLRequestJob* job =
+ URLRequestJobManager::GetInstance()->MaybeInterceptRedirect(this,
+ location);
if (job) {
RestartWithJob(job);
} else if (delegate_) {
@@ -439,7 +441,8 @@ void URLRequest::ResponseStarted() {
params = new net::NetLogIntegerParameter("net_error", status_.os_error());
net_log_.EndEvent(net::NetLog::TYPE_URL_REQUEST_START_JOB, params);
- URLRequestJob* job = GetJobManager()->MaybeInterceptResponse(this);
+ URLRequestJob* job =
+ URLRequestJobManager::GetInstance()->MaybeInterceptResponse(this);
if (job) {
RestartWithJob(job);
} else if (delegate_) {
@@ -598,3 +601,5 @@ URLRequest::UserData* URLRequest::GetUserData(const void* key) const {
void URLRequest::SetUserData(const void* key, UserData* data) {
user_data_[key] = linked_ptr<UserData>(data);
}
+
+} // namespace net
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index fb81500..ffd4f88 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -646,6 +646,4 @@ class URLRequest : public NonThreadSafe {
} // namespace net
-typedef net::URLRequest URLRequest;
-
#endif // NET_URL_REQUEST_URL_REQUEST_H_
diff --git a/net/url_request/url_request_about_job.cc b/net/url_request/url_request_about_job.cc
index ac6aa01..b8dab1a 100644
--- a/net/url_request/url_request_about_job.cc
+++ b/net/url_request/url_request_about_job.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.
@@ -10,6 +10,8 @@
#include "base/message_loop.h"
+namespace net {
+
// static
URLRequestJob* URLRequestAboutJob::Factory(URLRequest* request,
const std::string& scheme) {
@@ -38,3 +40,5 @@ URLRequestAboutJob::~URLRequestAboutJob() {
void URLRequestAboutJob::StartAsync() {
NotifyHeadersComplete();
}
+
+} // namespace net
diff --git a/net/url_request/url_request_about_job.h b/net/url_request/url_request_about_job.h
index 52a659e..7617208 100644
--- a/net/url_request/url_request_about_job.h
+++ b/net/url_request/url_request_about_job.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.
@@ -11,6 +11,8 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
+namespace net {
+
class URLRequestAboutJob : public URLRequestJob {
public:
explicit URLRequestAboutJob(URLRequest* request);
@@ -26,4 +28,6 @@ class URLRequestAboutJob : public URLRequestJob {
void StartAsync();
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_ABOUT_JOB_H_
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 281aa7e..3bc7da6 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -11,6 +11,7 @@
URLRequestContext::URLRequestContext()
: net_log_(NULL),
host_resolver_(NULL),
+ cert_verifier_(NULL),
dnsrr_resolver_(NULL),
dns_cert_checker_(NULL),
http_transaction_factory_(NULL),
@@ -28,3 +29,7 @@ const std::string& URLRequestContext::GetUserAgent(const GURL& url) const {
URLRequestContext::~URLRequestContext() {
}
+
+void URLRequestContext::set_cookie_store(net::CookieStore* cookie_store) {
+ cookie_store_ = cookie_store;
+}
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index bc601b3..d929696 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -21,6 +21,7 @@
#include "net/socket/dns_cert_provenance_checker.h"
namespace net {
+class CertVerifier;
class CookiePolicy;
class CookieStore;
class DnsCertProvenanceChecker;
@@ -34,7 +35,8 @@ class SSLConfigService;
class URLRequest;
} // namespace net
-// Subclass to provide application-specific context for URLRequest instances.
+// Subclass to provide application-specific context for net::URLRequest
+// instances.
class URLRequestContext
: public base::RefCountedThreadSafe<URLRequestContext>,
public NonThreadSafe {
@@ -45,14 +47,34 @@ class URLRequestContext
return net_log_;
}
+ void set_net_log(net::NetLog* net_log) {
+ net_log_ = net_log;
+ }
+
net::HostResolver* host_resolver() const {
return host_resolver_;
}
+ void set_host_resolver(net::HostResolver* host_resolver) {
+ host_resolver_ = host_resolver;
+ }
+
+ net::CertVerifier* cert_verifier() const {
+ return cert_verifier_;
+ }
+
+ void set_cert_verifier(net::CertVerifier* cert_verifier) {
+ cert_verifier_ = cert_verifier;
+ }
+
net::DnsRRResolver* dnsrr_resolver() const {
return dnsrr_resolver_;
}
+ void set_dnsrr_resolver(net::DnsRRResolver* dnsrr_resolver) {
+ dnsrr_resolver_ = dnsrr_resolver;
+ }
+
net::DnsCertProvenanceChecker* dns_cert_checker() const {
return dns_cert_checker_.get();
}
@@ -62,16 +84,33 @@ class URLRequestContext
return proxy_service_;
}
+ void set_proxy_service(net::ProxyService* proxy_service) {
+ proxy_service_ = proxy_service;
+ }
+
// Get the ssl config service for this context.
net::SSLConfigService* ssl_config_service() const {
return ssl_config_service_;
}
+ // Gets the HTTP Authentication Handler Factory for this context.
+ // The factory is only valid for the lifetime of this URLRequestContext
+ net::HttpAuthHandlerFactory* http_auth_handler_factory() {
+ return http_auth_handler_factory_;
+ }
+ void set_http_auth_handler_factory(net::HttpAuthHandlerFactory* factory) {
+ http_auth_handler_factory_ = factory;
+ }
+
// Gets the http transaction factory for this context.
net::HttpTransactionFactory* http_transaction_factory() const {
return http_transaction_factory_;
}
+ void set_http_transaction_factory(net::HttpTransactionFactory* factory) {
+ http_transaction_factory_ = factory;
+ }
+
// Gets the ftp transaction factory for this context.
net::FtpTransactionFactory* ftp_transaction_factory() {
return ftp_transaction_factory_;
@@ -81,6 +120,8 @@ class URLRequestContext
// cookies are not stored).
net::CookieStore* cookie_store() { return cookie_store_.get(); }
+ void set_cookie_store(net::CookieStore* cookie_store);
+
// Gets the cookie policy for this context (may be null, in which case
// cookies are allowed).
net::CookiePolicy* cookie_policy() { return cookie_policy_; }
@@ -91,12 +132,6 @@ class URLRequestContext
// Gets the FTP authentication cache for this context.
net::FtpAuthCache* ftp_auth_cache() { return &ftp_auth_cache_; }
- // Gets the HTTP Authentication Handler Factory for this context.
- // The factory is only valid for the lifetime of this URLRequestContext
- net::HttpAuthHandlerFactory* http_auth_handler_factory() {
- return http_auth_handler_factory_;
- }
-
// Gets the value of 'Accept-Charset' header field.
const std::string& accept_charset() const { return accept_charset_; }
@@ -134,6 +169,7 @@ class URLRequestContext
// subclasses.
net::NetLog* net_log_;
net::HostResolver* host_resolver_;
+ net::CertVerifier* cert_verifier_;
net::DnsRRResolver* dnsrr_resolver_;
scoped_ptr<net::DnsCertProvenanceChecker> dns_cert_checker_;
scoped_refptr<net::ProxyService> proxy_service_;
diff --git a/net/url_request/url_request_data_job.cc b/net/url_request/url_request_data_job.cc
index 737f169..30b22fb 100644
--- a/net/url_request/url_request_data_job.cc
+++ b/net/url_request/url_request_data_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 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,7 +7,8 @@
#include "net/url_request/url_request_data_job.h"
#include "net/base/data_url.h"
-#include "net/url_request/url_request.h"
+
+namespace net {
// static
URLRequestJob* URLRequestDataJob::Factory(URLRequest* request,
@@ -27,8 +28,10 @@ bool URLRequestDataJob::GetData(std::string* mime_type,
const GURL& url = request_->url();
if (!url.is_valid())
return false;
- return net::DataURL::Parse(url, mime_type, charset, data);
+ return DataURL::Parse(url, mime_type, charset, data);
}
URLRequestDataJob::~URLRequestDataJob() {
}
+
+} // namespace net
diff --git a/net/url_request/url_request_data_job.h b/net/url_request/url_request_data_job.h
index 7171088..e00d43c 100644
--- a/net/url_request/url_request_data_job.h
+++ b/net/url_request/url_request_data_job.h
@@ -12,18 +12,18 @@
#include "net/url_request/url_request_simple_job.h"
namespace net {
+
class URLRequest;
-} // namespace net
class URLRequestDataJob : public URLRequestSimpleJob {
public:
- explicit URLRequestDataJob(net::URLRequest* request);
+ explicit URLRequestDataJob(URLRequest* request);
virtual bool GetData(std::string* mime_type,
std::string* charset,
std::string* data) const;
- static net::URLRequest::ProtocolFactory Factory;
+ static URLRequest::ProtocolFactory Factory;
private:
~URLRequestDataJob();
@@ -31,4 +31,6 @@ class URLRequestDataJob : public URLRequestSimpleJob {
DISALLOW_COPY_AND_ASSIGN(URLRequestDataJob);
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_DATA_JOB_H_
diff --git a/net/url_request/url_request_error_job.cc b/net/url_request/url_request_error_job.cc
index 1aeffac..c69e3f5 100644
--- a/net/url_request/url_request_error_job.cc
+++ b/net/url_request/url_request_error_job.cc
@@ -8,7 +8,9 @@
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"
-URLRequestErrorJob::URLRequestErrorJob(net::URLRequest* request, int error)
+namespace net {
+
+URLRequestErrorJob::URLRequestErrorJob(URLRequest* request, int error)
: URLRequestJob(request), error_(error) {
}
@@ -20,3 +22,5 @@ void URLRequestErrorJob::Start() {
void URLRequestErrorJob::StartAsync() {
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error_));
}
+
+} // namespace net
diff --git a/net/url_request/url_request_error_job.h b/net/url_request/url_request_error_job.h
index 6e7c879..9d3ba7b 100644
--- a/net/url_request/url_request_error_job.h
+++ b/net/url_request/url_request_error_job.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Invalid URLs go through this URLRequestJob class rather than being passed
-// to the default job handler.
+// Invalid URLs go through this net::URLRequestJob class rather than being
+// passed to the default job handler.
#ifndef NET_URL_REQUEST_URL_REQUEST_ERROR_JOB_H_
#define NET_URL_REQUEST_URL_REQUEST_ERROR_JOB_H_
@@ -11,9 +11,11 @@
#include "net/url_request/url_request_job.h"
+namespace net {
+
class URLRequestErrorJob : public URLRequestJob {
public:
- URLRequestErrorJob(net::URLRequest* request, int error);
+ URLRequestErrorJob(URLRequest* request, int error);
virtual void Start();
@@ -25,4 +27,6 @@ class URLRequestErrorJob : public URLRequestJob {
int error_;
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_ERROR_JOB_H_
diff --git a/net/url_request/url_request_file_dir_job.cc b/net/url_request/url_request_file_dir_job.cc
index 23ff6ff..553add8 100644
--- a/net/url_request/url_request_file_dir_job.cc
+++ b/net/url_request/url_request_file_dir_job.cc
@@ -4,6 +4,7 @@
#include "net/url_request/url_request_file_dir_job.h"
+#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/sys_string_conversions.h"
@@ -20,15 +21,16 @@
using std::string;
-URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request,
+URLRequestFileDirJob::URLRequestFileDirJob(net::URLRequest* request,
const FilePath& dir_path)
- : URLRequestJob(request),
+ : net::URLRequestJob(request),
dir_path_(dir_path),
canceled_(false),
list_complete_(false),
wrote_header_(false),
read_pending_(false),
- read_buffer_length_(0) {
+ read_buffer_length_(0),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
}
URLRequestFileDirJob::~URLRequestFileDirJob() {
@@ -39,13 +41,18 @@ URLRequestFileDirJob::~URLRequestFileDirJob() {
void URLRequestFileDirJob::Start() {
// Start reading asynchronously so that all error reporting and data
// callbacks happen as they would for network requests.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFileDirJob::StartAsync));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestFileDirJob::StartAsync));
}
void URLRequestFileDirJob::StartAsync() {
DCHECK(!lister_);
+ // TODO(willchan): This is stupid. We should tell |lister_| not to call us
+ // back. Fix this stupidity.
+
// AddRef so that *this* cannot be destroyed while the lister_
// is trying to feed us data.
@@ -62,13 +69,15 @@ void URLRequestFileDirJob::Kill() {
canceled_ = true;
- // Don't call CloseLister or dispatch an error to the URLRequest because we
- // want OnListDone to be called to also write the error to the output stream.
- // OnListDone will notify the URLRequest at this time.
+ // Don't call CloseLister or dispatch an error to the net::URLRequest because
+ // we want OnListDone to be called to also write the error to the output
+ // stream. OnListDone will notify the net::URLRequest at this time.
if (lister_)
lister_->Cancel();
- URLRequestJob::Kill();
+ net::URLRequestJob::Kill();
+
+ method_factory_.RevokeAll();
}
bool URLRequestFileDirJob::ReadRawData(net::IOBuffer* buf, int buf_size,
diff --git a/net/url_request/url_request_file_dir_job.h b/net/url_request/url_request_file_dir_job.h
index aefaf5b..bdb9b37 100644
--- a/net/url_request/url_request_file_dir_job.h
+++ b/net/url_request/url_request_file_dir_job.h
@@ -10,16 +10,17 @@
#include "base/file_path.h"
#include "base/file_util.h"
+#include "base/task.h"
#include "net/base/directory_lister.h"
#include "net/url_request/url_request_job.h"
class URLRequestFileDirJob
- : public URLRequestJob,
+ : public net::URLRequestJob,
public net::DirectoryLister::DirectoryListerDelegate {
public:
URLRequestFileDirJob(net::URLRequest* request, const FilePath& dir_path);
- // URLRequestJob methods:
+ // net::URLRequestJob methods:
virtual void Start();
virtual void StartAsync();
virtual void Kill();
@@ -63,6 +64,7 @@ class URLRequestFileDirJob
bool read_pending_;
scoped_refptr<net::IOBuffer> read_buffer_;
int read_buffer_length_;
+ ScopedRunnableMethodFactory<URLRequestFileDirJob> method_factory_;
DISALLOW_COPY_AND_ASSIGN(URLRequestFileDirJob);
};
diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc
index 526dabf..230ee06 100644
--- a/net/url_request/url_request_file_job.cc
+++ b/net/url_request/url_request_file_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 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,6 +40,8 @@
#include "base/worker_pool.h"
#endif
+namespace net {
+
#if defined(OS_WIN)
class URLRequestFileJob::AsyncResolver
: public base::RefCountedThreadSafe<URLRequestFileJob::AsyncResolver> {
@@ -83,16 +85,16 @@ class URLRequestFileJob::AsyncResolver
#endif
// static
-URLRequestJob* URLRequestFileJob::Factory(
- URLRequest* request, const std::string& scheme) {
+URLRequestJob* URLRequestFileJob::Factory(URLRequest* request,
+ const std::string& scheme) {
FilePath file_path;
- const bool is_file = net::FileURLToFilePath(request->url(), &file_path);
+ const bool is_file = FileURLToFilePath(request->url(), &file_path);
#if defined(OS_CHROMEOS)
// Check file access.
if (AccessDisabled(file_path))
- return new URLRequestErrorJob(request, net::ERR_ACCESS_DENIED);
+ return new URLRequestErrorJob(request, ERR_ACCESS_DENIED);
#endif
// We need to decide whether to create URLRequestFileJob for file access or
@@ -118,7 +120,8 @@ URLRequestFileJob::URLRequestFileJob(URLRequest* request,
ALLOW_THIS_IN_INITIALIZER_LIST(
io_callback_(this, &URLRequestFileJob::DidRead)),
is_directory_(false),
- remaining_bytes_(0) {
+ remaining_bytes_(0),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
}
URLRequestFileJob::~URLRequestFileJob() {
@@ -149,8 +152,10 @@ void URLRequestFileJob::Start() {
}
// Continue asynchronously.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFileJob::DidResolve, exists, file_info));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestFileJob::DidResolve, exists, file_info));
}
void URLRequestFileJob::Kill() {
@@ -164,9 +169,10 @@ void URLRequestFileJob::Kill() {
#endif
URLRequestJob::Kill();
+ method_factory_.RevokeAll();
}
-bool URLRequestFileJob::ReadRawData(net::IOBuffer* dest, int dest_size,
+bool URLRequestFileJob::ReadRawData(IOBuffer* dest, int dest_size,
int *bytes_read) {
DCHECK_NE(dest_size, 0);
DCHECK(bytes_read);
@@ -192,7 +198,7 @@ bool URLRequestFileJob::ReadRawData(net::IOBuffer* dest, int dest_size,
}
// Otherwise, a read error occured. We may just need to wait...
- if (rv == net::ERR_IO_PENDING) {
+ if (rv == ERR_IO_PENDING) {
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
} else {
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
@@ -217,16 +223,16 @@ bool URLRequestFileJob::GetMimeType(std::string* mime_type) const {
// http://code.google.com/p/chromium/issues/detail?id=59849
base::ThreadRestrictions::ScopedAllowIO allow_io;
DCHECK(request_);
- return net::GetMimeTypeFromFile(file_path_, mime_type);
+ return GetMimeTypeFromFile(file_path_, mime_type);
}
void URLRequestFileJob::SetExtraRequestHeaders(
- const net::HttpRequestHeaders& headers) {
+ const HttpRequestHeaders& headers) {
std::string range_header;
- if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
+ if (headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) {
// We only care about "Range" header here.
- std::vector<net::HttpByteRange> ranges;
- if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+ std::vector<HttpByteRange> ranges;
+ if (HttpUtil::ParseRangeHeader(range_header, &ranges)) {
if (ranges.size() == 1) {
byte_range_ = ranges[0];
} else {
@@ -235,7 +241,7 @@ void URLRequestFileJob::SetExtraRequestHeaders(
// TODO(hclam): decide whether we want to support multiple range
// requests.
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
- net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ ERR_REQUEST_RANGE_NOT_SATISFIABLE));
}
}
}
@@ -253,7 +259,7 @@ void URLRequestFileJob::DidResolve(
is_directory_ = file_info.is_directory;
- int rv = net::OK;
+ int rv = OK;
// We use URLRequestFileJob to handle files as well as directories without
// trailing slash.
// If a directory does not exist, we return ERR_FILE_NOT_FOUND. Otherwise,
@@ -263,7 +269,7 @@ void URLRequestFileJob::DidResolve(
// So what happens is we append it with trailing slash and redirect it to
// FileDirJob where it is resolved as invalid.
if (!exists) {
- rv = net::ERR_FILE_NOT_FOUND;
+ rv = 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
@@ -275,14 +281,14 @@ void URLRequestFileJob::DidResolve(
rv = stream_.Open(file_path_, flags);
}
- if (rv != net::OK) {
+ if (rv != OK) {
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
return;
}
if (!byte_range_.ComputeBounds(file_info.size)) {
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
- net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ ERR_REQUEST_RANGE_NOT_SATISFIABLE));
return;
}
@@ -294,9 +300,9 @@ void URLRequestFileJob::DidResolve(
if (remaining_bytes_ > 0 &&
byte_range_.first_byte_position() != 0 &&
byte_range_.first_byte_position() !=
- stream_.Seek(net::FROM_BEGIN, byte_range_.first_byte_position())) {
+ stream_.Seek(FROM_BEGIN, byte_range_.first_byte_position())) {
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
- net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ ERR_REQUEST_RANGE_NOT_SATISFIABLE));
return;
}
@@ -348,7 +354,7 @@ bool URLRequestFileJob::IsRedirectResponse(GURL* location,
if (!resolved)
return false;
- *location = net::FilePathToFileURL(new_path);
+ *location = FilePathToFileURL(new_path);
*http_status_code = 301;
return true;
#else
@@ -359,6 +365,7 @@ bool URLRequestFileJob::IsRedirectResponse(GURL* location,
#if defined(OS_CHROMEOS)
static const char* const kLocalAccessWhiteList[] = {
"/home/chronos/user/Downloads",
+ "/media",
"/mnt/partner_partition",
"/usr/share/chromeos-assets",
"/tmp",
@@ -383,3 +390,4 @@ bool URLRequestFileJob::AccessDisabled(const FilePath& file_path) {
}
#endif
+} // namespace net
diff --git a/net/url_request/url_request_file_job.h b/net/url_request/url_request_file_job.h
index e745cfd..1a09b04 100644
--- a/net/url_request/url_request_file_job.h
+++ b/net/url_request/url_request_file_job.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/file_path.h"
+#include "base/task.h"
#include "net/base/completion_callback.h"
#include "net/base/file_stream.h"
#include "net/http/http_byte_range.h"
@@ -20,6 +21,8 @@ namespace file_util {
struct FileInfo;
}
+namespace net {
+
// A request job that handles reading file URLs
class URLRequestFileJob : public URLRequestJob {
public:
@@ -27,12 +30,12 @@ class URLRequestFileJob : public URLRequestJob {
virtual void Start();
virtual void Kill();
- virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
+ virtual bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read);
virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
virtual bool GetContentEncodings(
std::vector<Filter::FilterType>* encoding_type);
virtual bool GetMimeType(std::string* mime_type) const;
- virtual void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers);
+ virtual void SetExtraRequestHeaders(const HttpRequestHeaders& headers);
static URLRequest::ProtocolFactory Factory;
@@ -50,11 +53,11 @@ class URLRequestFileJob : public URLRequestJob {
void DidResolve(bool exists, const base::PlatformFileInfo& file_info);
void DidRead(int result);
- net::CompletionCallbackImpl<URLRequestFileJob> io_callback_;
- net::FileStream stream_;
+ CompletionCallbackImpl<URLRequestFileJob> io_callback_;
+ FileStream stream_;
bool is_directory_;
- net::HttpByteRange byte_range_;
+ HttpByteRange byte_range_;
int64 remaining_bytes_;
#if defined(OS_WIN)
@@ -63,7 +66,11 @@ class URLRequestFileJob : public URLRequestJob {
scoped_refptr<AsyncResolver> async_resolver_;
#endif
+ ScopedRunnableMethodFactory<URLRequestFileJob> method_factory_;
+
DISALLOW_COPY_AND_ASSIGN(URLRequestFileJob);
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_FILE_JOB_H_
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc
index fb305b2..946c2c3 100644
--- a/net/url_request/url_request_filter.cc
+++ b/net/url_request/url_request_filter.cc
@@ -27,12 +27,12 @@ net::URLRequestJob* URLRequestFilter::Factory(net::URLRequest* request,
URLRequestFilter::~URLRequestFilter() {}
void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
- const std::string& hostname, URLRequest::ProtocolFactory* factory) {
+ const std::string& hostname, net::URLRequest::ProtocolFactory* factory) {
hostname_handler_map_[make_pair(scheme, hostname)] = factory;
// Register with the ProtocolFactory.
- URLRequest::RegisterProtocolFactory(scheme,
- &URLRequestFilter::Factory);
+ net::URLRequest::RegisterProtocolFactory(scheme,
+ &URLRequestFilter::Factory);
#ifndef NDEBUG
// Check to see if we're masking URLs in the url_handler_map_.
@@ -54,20 +54,22 @@ void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
DCHECK(iter != hostname_handler_map_.end());
hostname_handler_map_.erase(iter);
- // Note that we don't unregister from the URLRequest ProtocolFactory as this
- // would left no protocol factory for the scheme. URLRequestFilter::Factory
- // will keep forwarding the requests to the URLRequestInetJob.
+ // Note that we don't unregister from the net::URLRequest ProtocolFactory as
+ // this would left no protocol factory for the scheme.
+ // URLRequestFilter::Factory will keep forwarding the requests to the
+ // URLRequestInetJob.
}
-bool URLRequestFilter::AddUrlHandler(const GURL& url,
- URLRequest::ProtocolFactory* factory) {
+bool URLRequestFilter::AddUrlHandler(
+ const GURL& url,
+ net::URLRequest::ProtocolFactory* factory) {
if (!url.is_valid())
return false;
url_handler_map_[url.spec()] = factory;
// Register with the ProtocolFactory.
- URLRequest::RegisterProtocolFactory(url.scheme(),
- &URLRequestFilter::Factory);
+ net::URLRequest::RegisterProtocolFactory(url.scheme(),
+ &URLRequestFilter::Factory);
#ifndef NDEBUG
// Check to see if this URL is masked by a hostname handler.
HostnameHandlerMap::iterator host_it =
@@ -84,9 +86,10 @@ void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
DCHECK(iter != url_handler_map_.end());
url_handler_map_.erase(iter);
- // Note that we don't unregister from the URLRequest ProtocolFactory as this
- // would left no protocol factory for the scheme. URLRequestFilter::Factory
- // will keep forwarding the requests to the URLRequestInetJob.
+ // Note that we don't unregister from the net::URLRequest ProtocolFactory as
+ // this would left no protocol factory for the scheme.
+ // URLRequestFilter::Factory will keep forwarding the requests to the
+ // URLRequestInetJob.
}
void URLRequestFilter::ClearHandlers() {
@@ -102,7 +105,7 @@ void URLRequestFilter::ClearHandlers() {
}
for (std::set<std::string>::const_iterator scheme = schemes.begin();
scheme != schemes.end(); ++scheme) {
- URLRequest::RegisterProtocolFactory(*scheme, NULL);
+ net::URLRequest::RegisterProtocolFactory(*scheme, NULL);
}
url_handler_map_.clear();
diff --git a/net/url_request/url_request_filter.h b/net/url_request/url_request_filter.h
index c3021cb..716ad4d 100644
--- a/net/url_request/url_request_filter.h
+++ b/net/url_request/url_request_filter.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// A class to help filter URLRequest jobs based on the URL of the request
+// A class to help filter net::URLRequest jobs based on the URL of the request
// rather than just the scheme. Example usage:
//
// // Use as an "http" handler.
-// URLRequest::RegisterProtocolFactory("http", &URLRequestFilter::Factory);
+// net::URLRequest::RegisterProtocolFactory("http", &URLRequestFilter::Factory);
// // Add special handling for the URL http://foo.com/
// URLRequestFilter::GetInstance()->AddUrlHandler(
// GURL("http://foo.com/"),
@@ -36,26 +36,27 @@ class URLRequestFilter {
public:
// scheme,hostname -> ProtocolFactory
typedef std::map<std::pair<std::string, std::string>,
- URLRequest::ProtocolFactory*> HostnameHandlerMap;
- typedef base::hash_map<std::string, URLRequest::ProtocolFactory*>
+ net::URLRequest::ProtocolFactory*> HostnameHandlerMap;
+ typedef base::hash_map<std::string, net::URLRequest::ProtocolFactory*>
UrlHandlerMap;
// Singleton instance for use.
static URLRequestFilter* GetInstance();
- static URLRequest::ProtocolFactory Factory;
+ static net::URLRequest::ProtocolFactory Factory;
~URLRequestFilter();
void AddHostnameHandler(const std::string& scheme,
const std::string& hostname,
- URLRequest::ProtocolFactory* factory);
+ net::URLRequest::ProtocolFactory* factory);
void RemoveHostnameHandler(const std::string& scheme,
const std::string& hostname);
// Returns true if we successfully added the URL handler. This will replace
// old handlers for the URL if one existed.
- bool AddUrlHandler(const GURL& url, URLRequest::ProtocolFactory* factory);
+ bool AddUrlHandler(const GURL& url,
+ net::URLRequest::ProtocolFactory* factory);
void RemoveUrlHandler(const GURL& url);
@@ -70,7 +71,7 @@ class URLRequestFilter {
URLRequestFilter();
// Helper method that looks up the request in the url_handler_map_.
- net::URLRequestJob* FindRequestHandler(URLRequest* request,
+ net::URLRequestJob* FindRequestHandler(net::URLRequest* request,
const std::string& scheme);
// Maps hostnames to factories. Hostnames take priority over URLs.
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index aec8248..ea9b23c 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -16,6 +16,8 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_error_job.h"
+namespace net {
+
URLRequestFtpJob::URLRequestFtpJob(URLRequest* request)
: URLRequestJob(request),
ALLOW_THIS_IN_INITIALIZER_LIST(
@@ -23,7 +25,8 @@ URLRequestFtpJob::URLRequestFtpJob(URLRequest* request)
ALLOW_THIS_IN_INITIALIZER_LIST(
read_callback_(this, &URLRequestFtpJob::OnReadCompleted)),
read_in_progress_(false),
- context_(request->context()) {
+ context_(request->context()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
}
URLRequestFtpJob::~URLRequestFtpJob() {
@@ -36,8 +39,8 @@ URLRequestJob* URLRequestFtpJob::Factory(URLRequest* request,
int port = request->url().IntPort();
if (request->url().has_port() &&
- !net::IsPortAllowedByFtp(port) && !net::IsPortAllowedByOverride(port))
- return new URLRequestErrorJob(request, net::ERR_UNSAFE_PORT);
+ !IsPortAllowedByFtp(port) && !IsPortAllowedByOverride(port))
+ return new URLRequestErrorJob(request, ERR_UNSAFE_PORT);
DCHECK(request->context());
DCHECK(request->context()->ftp_transaction_factory());
@@ -61,13 +64,14 @@ void URLRequestFtpJob::Start() {
void URLRequestFtpJob::Kill() {
if (!transaction_.get())
return;
- DestroyTransaction();
+ transaction_.reset();
URLRequestJob::Kill();
+ method_factory_.RevokeAll();
}
-net::LoadState URLRequestFtpJob::GetLoadState() const {
+LoadState URLRequestFtpJob::GetLoadState() const {
return transaction_.get() ?
- transaction_->GetLoadState() : net::LOAD_STATE_IDLE;
+ transaction_->GetLoadState() : LOAD_STATE_IDLE;
}
bool URLRequestFtpJob::NeedsAuth() {
@@ -75,17 +79,17 @@ bool URLRequestFtpJob::NeedsAuth() {
// requires auth (and not a proxy), because connecting to FTP via proxy
// effectively means the browser communicates via HTTP, and uses HTTP's
// Proxy-Authenticate protocol when proxy servers require auth.
- return server_auth_ && server_auth_->state == net::AUTH_STATE_NEED_AUTH;
+ return server_auth_ && server_auth_->state == AUTH_STATE_NEED_AUTH;
}
void URLRequestFtpJob::GetAuthChallengeInfo(
- scoped_refptr<net::AuthChallengeInfo>* result) {
+ scoped_refptr<AuthChallengeInfo>* result) {
DCHECK((server_auth_ != NULL) &&
- (server_auth_->state == net::AUTH_STATE_NEED_AUTH));
- scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
+ (server_auth_->state == AUTH_STATE_NEED_AUTH));
+ scoped_refptr<AuthChallengeInfo> auth_info(new AuthChallengeInfo);
auth_info->is_proxy = false;
auth_info->host_and_port = ASCIIToWide(
- net::GetHostAndPort(request_->url()));
+ GetHostAndPort(request_->url()));
auth_info->scheme = L"";
auth_info->realm = L"";
result->swap(auth_info);
@@ -94,7 +98,7 @@ void URLRequestFtpJob::GetAuthChallengeInfo(
void URLRequestFtpJob::SetAuth(const string16& username,
const string16& password) {
DCHECK(NeedsAuth());
- server_auth_->state = net::AUTH_STATE_HAVE_AUTH;
+ server_auth_->state = AUTH_STATE_HAVE_AUTH;
server_auth_->username = username;
server_auth_->password = password;
@@ -106,16 +110,22 @@ void URLRequestFtpJob::SetAuth(const string16& username,
void URLRequestFtpJob::CancelAuth() {
DCHECK(NeedsAuth());
- server_auth_->state = net::AUTH_STATE_CANCELED;
+ server_auth_->state = AUTH_STATE_CANCELED;
// Once the auth is cancelled, we proceed with the request as though
// there were no auth. Schedule this for later so that we don't cause
// any recursing into the caller as a result of this call.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFtpJob::OnStartCompleted, net::OK));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestFtpJob::OnStartCompleted, OK));
}
-bool URLRequestFtpJob::ReadRawData(net::IOBuffer* buf,
+uint64 URLRequestFtpJob::GetUploadProgress() const {
+ return 0;
+}
+
+bool URLRequestFtpJob::ReadRawData(IOBuffer* buf,
int buf_size,
int *bytes_read) {
DCHECK_NE(buf_size, 0);
@@ -128,7 +138,7 @@ bool URLRequestFtpJob::ReadRawData(net::IOBuffer* buf,
return true;
}
- if (rv == net::ERR_IO_PENDING) {
+ if (rv == ERR_IO_PENDING) {
read_in_progress_ = true;
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
} else {
@@ -138,13 +148,6 @@ bool URLRequestFtpJob::ReadRawData(net::IOBuffer* buf,
}
void URLRequestFtpJob::OnStartCompleted(int result) {
- // If the request was destroyed, then there is no more work to do.
- if (!request_ || !request_->delegate())
- return;
- // If the transaction was destroyed, then the job was cancelled, and
- // we can just ignore this notification.
- if (!transaction_.get())
- return;
// Clear the IO_PENDING status
SetStatus(URLRequestStatus());
@@ -153,20 +156,20 @@ void URLRequestFtpJob::OnStartCompleted(int result) {
set_expected_content_size(
transaction_->GetResponseInfo()->expected_content_size);
- if (result == net::OK) {
+ if (result == OK) {
NotifyHeadersComplete();
} else if (transaction_->GetResponseInfo()->needs_auth) {
GURL origin = request_->url().GetOrigin();
- if (server_auth_ && server_auth_->state == net::AUTH_STATE_HAVE_AUTH) {
+ if (server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH) {
request_->context()->ftp_auth_cache()->Remove(origin,
server_auth_->username,
server_auth_->password);
} else if (!server_auth_) {
- server_auth_ = new net::AuthData();
+ server_auth_ = new AuthData();
}
- server_auth_->state = net::AUTH_STATE_NEED_AUTH;
+ server_auth_->state = AUTH_STATE_NEED_AUTH;
- net::FtpAuthCache::Entry* cached_auth =
+ FtpAuthCache::Entry* cached_auth =
request_->context()->ftp_auth_cache()->Lookup(origin);
if (cached_auth) {
@@ -195,7 +198,7 @@ void URLRequestFtpJob::OnReadCompleted(int result) {
}
void URLRequestFtpJob::RestartTransactionWithAuth() {
- DCHECK(server_auth_ && server_auth_->state == net::AUTH_STATE_HAVE_AUTH);
+ DCHECK(server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH);
// No matter what, we want to report our status as IO pending since we will
// be notifying our consumer asynchronously via OnStartCompleted.
@@ -204,7 +207,7 @@ void URLRequestFtpJob::RestartTransactionWithAuth() {
int rv = transaction_->RestartWithAuth(server_auth_->username,
server_auth_->password,
&start_callback_);
- if (rv == net::ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING)
return;
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
@@ -218,7 +221,7 @@ void URLRequestFtpJob::StartTransaction() {
DCHECK(request_->context()->ftp_transaction_factory());
transaction_.reset(
- request_->context()->ftp_transaction_factory()->CreateTransaction());
+ request_->context()->ftp_transaction_factory()->CreateTransaction());
// No matter what, we want to report our status as IO pending since we will
// be notifying our consumer asynchronously via OnStartCompleted.
@@ -227,19 +230,17 @@ void URLRequestFtpJob::StartTransaction() {
if (transaction_.get()) {
rv = transaction_->Start(
&request_info_, &start_callback_, request_->net_log());
- if (rv == net::ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING)
return;
} else {
- rv = net::ERR_FAILED;
+ rv = ERR_FAILED;
}
// The transaction started synchronously, but we need to notify the
// URLRequest delegate via the message loop.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestFtpJob::OnStartCompleted, rv));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestFtpJob::OnStartCompleted, rv));
}
-void URLRequestFtpJob::DestroyTransaction() {
- DCHECK(transaction_.get());
-
- transaction_.reset();
-}
+} // namespace net
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h
index bd2fdc8..d503766 100644
--- a/net/url_request/url_request_ftp_job.h
+++ b/net/url_request/url_request_ftp_job.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/string16.h"
+#include "base/task.h"
#include "net/base/auth.h"
#include "net/base/completion_callback.h"
#include "net/ftp/ftp_request_info.h"
@@ -17,38 +18,39 @@
class URLRequestContext;
+namespace net {
+
// A URLRequestJob subclass that is built on top of FtpTransaction. It
// provides an implementation for FTP.
class URLRequestFtpJob : public URLRequestJob {
public:
- explicit URLRequestFtpJob(net::URLRequest* request);
+ explicit URLRequestFtpJob(URLRequest* request);
- static URLRequestJob* Factory(net::URLRequest* request,
+ static URLRequestJob* Factory(URLRequest* request,
const std::string& scheme);
- // URLRequestJob methods:
+ // Overridden from URLRequestJob:
virtual bool GetMimeType(std::string* mime_type) const;
private:
virtual ~URLRequestFtpJob();
- // URLRequestJob methods:
+ // Overridden from URLRequestJob:
virtual void Start();
virtual void Kill();
- virtual net::LoadState GetLoadState() const;
+ virtual LoadState GetLoadState() const;
virtual bool NeedsAuth();
virtual void GetAuthChallengeInfo(
- scoped_refptr<net::AuthChallengeInfo>* auth_info);
+ scoped_refptr<AuthChallengeInfo>* auth_info);
virtual void SetAuth(const string16& username,
const string16& password);
virtual void CancelAuth();
// TODO(ibrar): Yet to give another look at this function.
- virtual uint64 GetUploadProgress() const { return 0; }
- virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
+ virtual uint64 GetUploadProgress() const;
+ virtual bool ReadRawData(IOBuffer* buf, int buf_size, int *bytes_read);
- void DestroyTransaction();
void StartTransaction();
void OnStartCompleted(int result);
@@ -58,21 +60,25 @@ class URLRequestFtpJob : public URLRequestJob {
void LogFtpServerType(char server_type);
- net::FtpRequestInfo request_info_;
- scoped_ptr<net::FtpTransaction> transaction_;
+ FtpRequestInfo request_info_;
+ scoped_ptr<FtpTransaction> transaction_;
- net::CompletionCallbackImpl<URLRequestFtpJob> start_callback_;
- net::CompletionCallbackImpl<URLRequestFtpJob> read_callback_;
+ CompletionCallbackImpl<URLRequestFtpJob> start_callback_;
+ CompletionCallbackImpl<URLRequestFtpJob> read_callback_;
bool read_in_progress_;
- scoped_refptr<net::AuthData> server_auth_;
+ scoped_refptr<AuthData> server_auth_;
// Keep a reference to the url request context to be sure it's not deleted
// before us.
scoped_refptr<URLRequestContext> context_;
+ ScopedRunnableMethodFactory<URLRequestFtpJob> method_factory_;
+
DISALLOW_COPY_AND_ASSIGN(URLRequestFtpJob);
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_FTP_JOB_H_
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index af98de5..5457855 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -38,6 +38,46 @@
static const char kAvailDictionaryHeader[] = "Avail-Dictionary";
+namespace net {
+
+namespace {
+
+class HTTPSProberDelegateImpl : public HTTPSProberDelegate {
+ public:
+ HTTPSProberDelegateImpl(const std::string& host, int max_age,
+ bool include_subdomains,
+ TransportSecurityState* sts)
+ : host_(host),
+ max_age_(max_age),
+ include_subdomains_(include_subdomains),
+ sts_(sts) { }
+
+ virtual void ProbeComplete(bool result) {
+ if (result) {
+ base::Time current_time(base::Time::Now());
+ base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age_);
+
+ TransportSecurityState::DomainState domain_state;
+ domain_state.expiry = current_time + max_age_delta;
+ domain_state.mode =
+ TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
+ domain_state.include_subdomains = include_subdomains_;
+
+ sts_->EnableHost(host_, domain_state);
+ }
+
+ delete this;
+ }
+
+ private:
+ const std::string host_;
+ const int max_age_;
+ const bool include_subdomains_;
+ scoped_refptr<TransportSecurityState> sts_;
+};
+
+} // namespace
+
// TODO(darin): make sure the port blocking code is not lost
// static
URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
@@ -45,23 +85,23 @@ URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
DCHECK(scheme == "http" || scheme == "https");
int port = request->url().IntPort();
- if (!net::IsPortAllowedByDefault(port) && !net::IsPortAllowedByOverride(port))
- return new URLRequestErrorJob(request, net::ERR_UNSAFE_PORT);
+ if (!IsPortAllowedByDefault(port) && !IsPortAllowedByOverride(port))
+ return new URLRequestErrorJob(request, ERR_UNSAFE_PORT);
if (!request->context() ||
!request->context()->http_transaction_factory()) {
NOTREACHED() << "requires a valid context";
- return new URLRequestErrorJob(request, net::ERR_INVALID_ARGUMENT);
+ return new URLRequestErrorJob(request, ERR_INVALID_ARGUMENT);
}
- net::TransportSecurityState::DomainState domain_state;
+ TransportSecurityState::DomainState domain_state;
if (scheme == "http" &&
(request->url().port().empty() || port == 80) &&
request->context()->transport_security_state() &&
request->context()->transport_security_state()->IsEnabledForHost(
&domain_state, request->url().host())) {
if (domain_state.mode ==
- net::TransportSecurityState::DomainState::MODE_STRICT) {
+ TransportSecurityState::DomainState::MODE_STRICT) {
DCHECK_EQ(request->url().scheme(), "http");
url_canon::Replacements<char> replacements;
static const char kNewScheme[] = "https";
@@ -81,8 +121,8 @@ URLRequestHttpJob::URLRequestHttpJob(URLRequest* request)
: URLRequestJob(request),
response_info_(NULL),
response_cookies_save_index_(0),
- proxy_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH),
- server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH),
+ proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
+ server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
ALLOW_THIS_IN_INITIALIZER_LIST(can_get_cookies_callback_(
this, &URLRequestHttpJob::OnCanGetCookiesCompleted)),
ALLOW_THIS_IN_INITIALIZER_LIST(can_set_cookie_callback_(
@@ -93,12 +133,13 @@ URLRequestHttpJob::URLRequestHttpJob(URLRequest* request)
this, &URLRequestHttpJob::OnReadCompleted)),
read_in_progress_(false),
transaction_(NULL),
- throttling_entry_(net::URLRequestThrottlerManager::GetInstance()->
+ throttling_entry_(URLRequestThrottlerManager::GetInstance()->
RegisterRequestUrl(request->url())),
sdch_dictionary_advertised_(false),
sdch_test_activated_(false),
sdch_test_control_(false),
- is_cached_content_(false) {
+ is_cached_content_(false),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
}
URLRequestHttpJob::~URLRequestHttpJob() {
@@ -129,13 +170,13 @@ URLRequestHttpJob::~URLRequestHttpJob() {
}
}
-void URLRequestHttpJob::SetUpload(net::UploadData* upload) {
+void URLRequestHttpJob::SetUpload(UploadData* upload) {
DCHECK(!transaction_.get()) << "cannot change once started";
request_info_.upload_data = upload;
}
void URLRequestHttpJob::SetExtraRequestHeaders(
- const net::HttpRequestHeaders& headers) {
+ const HttpRequestHeaders& headers) {
DCHECK(!transaction_.get()) << "cannot change once started";
request_info_.extra_headers.CopyFrom(headers);
}
@@ -154,7 +195,7 @@ void URLRequestHttpJob::Start() {
if (request_->context()) {
request_info_.extra_headers.SetHeader(
- net::HttpRequestHeaders::kUserAgent,
+ HttpRequestHeaders::kUserAgent,
request_->context()->GetUserAgent(request_->url()));
}
@@ -170,9 +211,9 @@ void URLRequestHttpJob::Kill() {
URLRequestJob::Kill();
}
-net::LoadState URLRequestHttpJob::GetLoadState() const {
+LoadState URLRequestHttpJob::GetLoadState() const {
return transaction_.get() ?
- transaction_->GetLoadState() : net::LOAD_STATE_IDLE;
+ transaction_->GetLoadState() : LOAD_STATE_IDLE;
}
uint64 URLRequestHttpJob::GetUploadProgress() const {
@@ -197,7 +238,7 @@ bool URLRequestHttpJob::GetCharset(std::string* charset) {
return response_info_->headers->GetCharset(charset);
}
-void URLRequestHttpJob::GetResponseInfo(net::HttpResponseInfo* info) {
+void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
DCHECK(request_);
DCHECK(transaction_.get());
@@ -252,6 +293,10 @@ bool URLRequestHttpJob::GetContentEncodings(
return !encoding_types->empty();
}
+bool URLRequestHttpJob::IsCachedContent() const {
+ return is_cached_content_;
+}
+
bool URLRequestHttpJob::IsSdchResponse() const {
return sdch_dictionary_advertised_;
}
@@ -287,27 +332,27 @@ bool URLRequestHttpJob::NeedsAuth() {
// because we either provided no auth info, or provided incorrect info.
switch (code) {
case 407:
- if (proxy_auth_state_ == net::AUTH_STATE_CANCELED)
+ if (proxy_auth_state_ == AUTH_STATE_CANCELED)
return false;
- proxy_auth_state_ = net::AUTH_STATE_NEED_AUTH;
+ proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
return true;
case 401:
- if (server_auth_state_ == net::AUTH_STATE_CANCELED)
+ if (server_auth_state_ == AUTH_STATE_CANCELED)
return false;
- server_auth_state_ = net::AUTH_STATE_NEED_AUTH;
+ server_auth_state_ = AUTH_STATE_NEED_AUTH;
return true;
}
return false;
}
void URLRequestHttpJob::GetAuthChallengeInfo(
- scoped_refptr<net::AuthChallengeInfo>* result) {
+ scoped_refptr<AuthChallengeInfo>* result) {
DCHECK(transaction_.get());
DCHECK(response_info_);
// sanity checks:
- DCHECK(proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH ||
- server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
+ DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
+ server_auth_state_ == AUTH_STATE_NEED_AUTH);
DCHECK(response_info_->headers->response_code() == 401 ||
response_info_->headers->response_code() == 407);
@@ -319,11 +364,11 @@ void URLRequestHttpJob::SetAuth(const string16& username,
DCHECK(transaction_.get());
// Proxy gets set first, then WWW.
- if (proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH) {
- proxy_auth_state_ = net::AUTH_STATE_HAVE_AUTH;
+ if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
+ proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
} else {
- DCHECK(server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
- server_auth_state_ = net::AUTH_STATE_HAVE_AUTH;
+ DCHECK(server_auth_state_ == AUTH_STATE_NEED_AUTH);
+ server_auth_state_ = AUTH_STATE_HAVE_AUTH;
}
RestartTransactionWithAuth(username, password);
@@ -343,18 +388,18 @@ void URLRequestHttpJob::RestartTransactionWithAuth(
// headers in the 401/407. Since cookies were already appended to
// extra_headers, we need to strip them out before adding them again.
request_info_.extra_headers.RemoveHeader(
- net::HttpRequestHeaders::kCookie);
+ HttpRequestHeaders::kCookie);
AddCookieHeaderAndStart();
}
void URLRequestHttpJob::CancelAuth() {
// Proxy gets set first, then WWW.
- if (proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH) {
- proxy_auth_state_ = net::AUTH_STATE_CANCELED;
+ if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
+ proxy_auth_state_ = AUTH_STATE_CANCELED;
} else {
- DCHECK(server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
- server_auth_state_ = net::AUTH_STATE_CANCELED;
+ DCHECK(server_auth_state_ == AUTH_STATE_NEED_AUTH);
+ server_auth_state_ = AUTH_STATE_CANCELED;
}
// These will be reset in OnStartCompleted.
@@ -369,12 +414,14 @@ void URLRequestHttpJob::CancelAuth() {
//
// We have to do this via InvokeLater to avoid "recursing" the consumer.
//
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestHttpJob::OnStartCompleted, net::OK));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestHttpJob::OnStartCompleted, OK));
}
void URLRequestHttpJob::ContinueWithCertificate(
- net::X509Certificate* client_cert) {
+ X509Certificate* client_cert) {
DCHECK(transaction_.get());
DCHECK(!response_info_) << "should not have a response yet";
@@ -384,13 +431,15 @@ void URLRequestHttpJob::ContinueWithCertificate(
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
int rv = transaction_->RestartWithCertificate(client_cert, &start_callback_);
- if (rv == net::ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING)
return;
// The transaction started synchronously, but we need to notify the
// URLRequest delegate via the message loop.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestHttpJob::OnStartCompleted, rv));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestHttpJob::OnStartCompleted, rv));
}
void URLRequestHttpJob::ContinueDespiteLastError() {
@@ -405,16 +454,18 @@ void URLRequestHttpJob::ContinueDespiteLastError() {
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
int rv = transaction_->RestartIgnoringLastError(&start_callback_);
- if (rv == net::ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING)
return;
// The transaction started synchronously, but we need to notify the
// URLRequest delegate via the message loop.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestHttpJob::OnStartCompleted, rv));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestHttpJob::OnStartCompleted, rv));
}
-bool URLRequestHttpJob::ReadRawData(net::IOBuffer* buf, int buf_size,
+bool URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size,
int *bytes_read) {
DCHECK_NE(buf_size, 0);
DCHECK(bytes_read);
@@ -426,7 +477,7 @@ bool URLRequestHttpJob::ReadRawData(net::IOBuffer* buf, int buf_size,
return true;
}
- if (rv == net::ERR_IO_PENDING) {
+ if (rv == ERR_IO_PENDING) {
read_in_progress_ = true;
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
} else {
@@ -444,18 +495,20 @@ void URLRequestHttpJob::StopCaching() {
void URLRequestHttpJob::OnCanGetCookiesCompleted(int policy) {
// If the request was destroyed, then there is no more work to do.
if (request_ && request_->delegate()) {
- if (policy == net::ERR_ACCESS_DENIED) {
- request_->delegate()->OnGetCookies(request_, true);
- } else if (policy == net::OK && request_->context()->cookie_store()) {
- request_->delegate()->OnGetCookies(request_, false);
- net::CookieOptions options;
- options.set_include_httponly();
- std::string cookies =
- request_->context()->cookie_store()->GetCookiesWithOptions(
- request_->url(), options);
- if (!cookies.empty()) {
- request_info_.extra_headers.SetHeader(
- net::HttpRequestHeaders::kCookie, cookies);
+ if (request_->context()->cookie_store()) {
+ if (policy == ERR_ACCESS_DENIED) {
+ request_->delegate()->OnGetCookies(request_, true);
+ } else if (policy == OK) {
+ request_->delegate()->OnGetCookies(request_, false);
+ CookieOptions options;
+ options.set_include_httponly();
+ std::string cookies =
+ request_->context()->cookie_store()->GetCookiesWithOptions(
+ request_->url(), options);
+ if (!cookies.empty()) {
+ request_info_.extra_headers.SetHeader(
+ HttpRequestHeaders::kCookie, cookies);
+ }
}
}
// We may have been canceled within OnGetCookies.
@@ -471,27 +524,28 @@ void URLRequestHttpJob::OnCanGetCookiesCompleted(int policy) {
void URLRequestHttpJob::OnCanSetCookieCompleted(int policy) {
// If the request was destroyed, then there is no more work to do.
if (request_ && request_->delegate()) {
- if (policy == net::ERR_ACCESS_DENIED) {
- request_->delegate()->OnSetCookie(
- request_,
- response_cookies_[response_cookies_save_index_],
- net::CookieOptions(),
- true);
- } else if ((policy == net::OK || policy == net::OK_FOR_SESSION_ONLY) &&
- request_->context()->cookie_store()) {
- // OK to save the current response cookie now.
- net::CookieOptions options;
- options.set_include_httponly();
- if (policy == net::OK_FOR_SESSION_ONLY)
- options.set_force_session();
- request_->context()->cookie_store()->SetCookieWithOptions(
- request_->url(), response_cookies_[response_cookies_save_index_],
- options);
- request_->delegate()->OnSetCookie(
- request_,
- response_cookies_[response_cookies_save_index_],
- options,
- false);
+ if (request_->context()->cookie_store()) {
+ if (policy == ERR_ACCESS_DENIED) {
+ request_->delegate()->OnSetCookie(
+ request_,
+ response_cookies_[response_cookies_save_index_],
+ CookieOptions(),
+ true);
+ } else if (policy == OK || policy == OK_FOR_SESSION_ONLY) {
+ // OK to save the current response cookie now.
+ CookieOptions options;
+ options.set_include_httponly();
+ if (policy == OK_FOR_SESSION_ONLY)
+ options.set_force_session();
+ request_->context()->cookie_store()->SetCookieWithOptions(
+ request_->url(), response_cookies_[response_cookies_save_index_],
+ options);
+ request_->delegate()->OnSetCookie(
+ request_,
+ response_cookies_[response_cookies_save_index_],
+ options,
+ false);
+ }
}
response_cookies_save_index_++;
// We may have been canceled within OnSetCookie.
@@ -517,7 +571,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
// Clear the IO_PENDING status
SetStatus(URLRequestStatus());
- if (result == net::OK) {
+ if (result == OK) {
SaveCookiesAndNotifyHeadersComplete();
} else if (ShouldTreatAsCertificateError(result)) {
// We encountered an SSL certificate error. Ask our delegate to decide
@@ -526,7 +580,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
// ssl_info.
request_->delegate()->OnSSLCertificateError(
request_, result, transaction_->GetResponseInfo()->ssl_info.cert);
- } else if (result == net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
request_->delegate()->OnCertificateRequested(
request_, transaction_->GetResponseInfo()->cert_request_info);
} else {
@@ -550,20 +604,20 @@ void URLRequestHttpJob::OnReadCompleted(int result) {
}
bool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
- if (!net::IsCertificateError(result))
+ if (!IsCertificateError(result))
return false;
// Check whether our context is using Strict-Transport-Security.
if (!context_->transport_security_state())
return true;
- net::TransportSecurityState::DomainState domain_state;
+ TransportSecurityState::DomainState domain_state;
// TODO(agl): don't ignore opportunistic mode.
const bool r = context_->transport_security_state()->IsEnabledForHost(
&domain_state, request_info_.url.host());
return !r || domain_state.mode ==
- net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
+ TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
}
void URLRequestHttpJob::NotifyHeadersComplete() {
@@ -576,7 +630,7 @@ void URLRequestHttpJob::NotifyHeadersComplete() {
is_cached_content_ = response_info_->was_cached;
if (!is_cached_content_) {
- net::URLRequestThrottlerHeaderAdapter response_adapter(
+ URLRequestThrottlerHeaderAdapter response_adapter(
response_info_->headers);
throttling_entry_->UpdateWithResponse(&response_adapter);
}
@@ -641,22 +695,31 @@ void URLRequestHttpJob::StartTransaction() {
rv = request_->context()->http_transaction_factory()->CreateTransaction(
&transaction_);
- if (rv == net::OK) {
- rv = transaction_->Start(
- &request_info_, &start_callback_, request_->net_log());
+ if (rv == OK) {
+ if (!throttling_entry_->IsDuringExponentialBackoff() ||
+ !net::URLRequestThrottlerManager::GetInstance()->
+ enforce_throttling()) {
+ rv = transaction_->Start(
+ &request_info_, &start_callback_, request_->net_log());
+ } else {
+ // Special error code for the exponential back-off module.
+ rv = ERR_TEMPORARILY_THROTTLED;
+ }
// Make sure the context is alive for the duration of the
// transaction.
context_ = request_->context();
}
}
- if (rv == net::ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING)
return;
// The transaction started synchronously, but we need to notify the
// URLRequest delegate via the message loop.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &URLRequestHttpJob::OnStartCompleted, rv));
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &URLRequestHttpJob::OnStartCompleted, rv));
}
void URLRequestHttpJob::AddExtraHeaders() {
@@ -695,11 +758,11 @@ void URLRequestHttpJob::AddExtraHeaders() {
if (!advertise_sdch) {
// Tell the server what compression formats we support (other than SDCH).
request_info_.extra_headers.SetHeader(
- net::HttpRequestHeaders::kAcceptEncoding, "gzip,deflate");
+ HttpRequestHeaders::kAcceptEncoding, "gzip,deflate");
} else {
// Include SDCH in acceptable list.
request_info_.extra_headers.SetHeader(
- net::HttpRequestHeaders::kAcceptEncoding, "gzip,deflate,sdch");
+ HttpRequestHeaders::kAcceptEncoding, "gzip,deflate,sdch");
if (!avail_dictionaries.empty()) {
request_info_.extra_headers.SetHeader(
kAvailDictionaryHeader,
@@ -718,19 +781,23 @@ void URLRequestHttpJob::AddExtraHeaders() {
// Only add default Accept-Language and Accept-Charset if the request
// didn't have them specified.
if (!request_info_.extra_headers.HasHeader(
- net::HttpRequestHeaders::kAcceptLanguage)) {
+ HttpRequestHeaders::kAcceptLanguage)) {
request_info_.extra_headers.SetHeader(
+<<<<<<< HEAD
net::HttpRequestHeaders::kAcceptLanguage,
#ifdef ANDROID
context->GetAcceptLanguage());
#else
+=======
+ HttpRequestHeaders::kAcceptLanguage,
+>>>>>>> chromium.org at r10.0.621.0
context->accept_language());
#endif
}
if (!request_info_.extra_headers.HasHeader(
- net::HttpRequestHeaders::kAcceptCharset)) {
+ HttpRequestHeaders::kAcceptCharset)) {
request_info_.extra_headers.SetHeader(
- net::HttpRequestHeaders::kAcceptCharset,
+ HttpRequestHeaders::kAcceptCharset,
context->accept_charset());
}
}
@@ -743,16 +810,16 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() {
AddRef(); // Balanced in OnCanGetCookiesCompleted
- int policy = net::OK;
+ int policy = OK;
- if (request_info_.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) {
- policy = net::ERR_FAILED;
+ if (request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES) {
+ policy = ERR_FAILED;
} else if (request_->context()->cookie_policy()) {
policy = request_->context()->cookie_policy()->CanGetCookies(
request_->url(),
request_->first_party_for_cookies(),
&can_get_cookies_callback_);
- if (policy == net::ERR_IO_PENDING)
+ if (policy == ERR_IO_PENDING)
return; // Wait for completion callback
}
@@ -762,7 +829,7 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() {
void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete() {
DCHECK(transaction_.get());
- const net::HttpResponseInfo* response_info = transaction_->GetResponseInfo();
+ const HttpResponseInfo* response_info = transaction_->GetResponseInfo();
DCHECK(response_info);
response_cookies_.clear();
@@ -789,17 +856,17 @@ void URLRequestHttpJob::SaveNextCookie() {
AddRef(); // Balanced in OnCanSetCookieCompleted
- int policy = net::OK;
+ int policy = OK;
- if (request_info_.load_flags & net::LOAD_DO_NOT_SAVE_COOKIES) {
- policy = net::ERR_FAILED;
+ if (request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) {
+ policy = ERR_FAILED;
} else if (request_->context()->cookie_policy()) {
policy = request_->context()->cookie_policy()->CanSetCookie(
request_->url(),
request_->first_party_for_cookies(),
response_cookies_[response_cookies_save_index_],
&can_set_cookie_callback_);
- if (policy == net::ERR_IO_PENDING)
+ if (policy == ERR_IO_PENDING)
return; // Wait for completion callback
}
@@ -807,7 +874,7 @@ void URLRequestHttpJob::SaveNextCookie() {
}
void URLRequestHttpJob::FetchResponseCookies(
- const net::HttpResponseInfo* response_info,
+ const HttpResponseInfo* response_info,
std::vector<std::string>* cookies) {
std::string name = "Set-Cookie";
std::string value;
@@ -819,40 +886,6 @@ void URLRequestHttpJob::FetchResponseCookies(
}
}
-class HTTPSProberDelegate : public net::HTTPSProberDelegate {
- public:
- HTTPSProberDelegate(const std::string& host, int max_age,
- bool include_subdomains,
- net::TransportSecurityState* sts)
- : host_(host),
- max_age_(max_age),
- include_subdomains_(include_subdomains),
- sts_(sts) { }
-
- virtual void ProbeComplete(bool result) {
- if (result) {
- base::Time current_time(base::Time::Now());
- base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age_);
-
- net::TransportSecurityState::DomainState domain_state;
- domain_state.expiry = current_time + max_age_delta;
- domain_state.mode =
- net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
- domain_state.include_subdomains = include_subdomains_;
-
- sts_->EnableHost(host_, domain_state);
- }
-
- delete this;
- }
-
- private:
- const std::string host_;
- const int max_age_;
- const bool include_subdomains_;
- scoped_refptr<net::TransportSecurityState> sts_;
-};
-
void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
DCHECK(response_info_);
@@ -862,7 +895,7 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
const bool https = response_info_->ssl_info.is_valid();
const bool valid_https =
- https && !net::IsCertStatusError(response_info_->ssl_info.cert_status);
+ https && !IsCertStatusError(response_info_->ssl_info.cert_status);
std::string name = "Strict-Transport-Security";
std::string value;
@@ -872,7 +905,7 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
void* iter = NULL;
while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
- const bool ok = net::TransportSecurityState::ParseHeader(
+ const bool ok = TransportSecurityState::ParseHeader(
value, &max_age, &include_subdomains);
if (!ok)
continue;
@@ -883,9 +916,9 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
base::Time current_time(base::Time::Now());
base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
- net::TransportSecurityState::DomainState domain_state;
+ TransportSecurityState::DomainState domain_state;
domain_state.expiry = current_time + max_age_delta;
- domain_state.mode = net::TransportSecurityState::DomainState::MODE_STRICT;
+ domain_state.mode = TransportSecurityState::DomainState::MODE_STRICT;
domain_state.include_subdomains = include_subdomains;
ctx->transport_security_state()->EnableHost(request_info_.url.host(),
@@ -897,7 +930,7 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
name = "X-Bodge-Transport-Security";
while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
- const bool ok = net::TransportSecurityState::ParseHeader(
+ const bool ok = TransportSecurityState::ParseHeader(
value, &max_age, &include_subdomains);
if (!ok)
continue;
@@ -907,10 +940,10 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
base::Time current_time(base::Time::Now());
base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
- net::TransportSecurityState::DomainState domain_state;
+ TransportSecurityState::DomainState domain_state;
domain_state.expiry = current_time + max_age_delta;
domain_state.mode =
- net::TransportSecurityState::DomainState::MODE_SPDY_ONLY;
+ TransportSecurityState::DomainState::MODE_SPDY_ONLY;
domain_state.include_subdomains = include_subdomains;
ctx->transport_security_state()->EnableHost(request_info_.url.host(),
@@ -924,19 +957,21 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
// At this point, we have a request for opportunistic encryption over HTTP.
// In this case we need to probe to check that we can make HTTPS
// connections to that host.
- net::HTTPSProber* const prober = Singleton<net::HTTPSProber>::get();
+ HTTPSProber* const prober = HTTPSProber::GetInstance();
if (prober->HaveProbed(request_info_.url.host()) ||
prober->InFlight(request_info_.url.host())) {
continue;
}
- HTTPSProberDelegate* delegate =
- new HTTPSProberDelegate(request_info_.url.host(), max_age,
- include_subdomains,
- ctx->transport_security_state());
+ HTTPSProberDelegateImpl* delegate =
+ new HTTPSProberDelegateImpl(request_info_.url.host(), max_age,
+ include_subdomains,
+ ctx->transport_security_state());
if (!prober->ProbeHost(request_info_.url.host(), request()->context(),
delegate)) {
delete delegate;
}
}
}
+
+} // namespace net
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index c9139b0..78778c5 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -11,53 +11,55 @@
#include "base/scoped_ptr.h"
#include "base/string16.h"
+#include "base/task.h"
#include "net/base/auth.h"
#include "net/base/completion_callback.h"
#include "net/http/http_request_info.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_throttler_entry_interface.h"
+class URLRequestContext;
+
namespace net {
+
class HttpResponseInfo;
class HttpTransaction;
-}
-class URLRequestContext;
-// A URLRequestJob subclass that is built on top of HttpTransaction. It
+// A net::URLRequestJob subclass that is built on top of HttpTransaction. It
// provides an implementation for both HTTP and HTTPS.
class URLRequestHttpJob : public URLRequestJob {
public:
- static URLRequestJob* Factory(net::URLRequest* request,
+ static URLRequestJob* Factory(URLRequest* request,
const std::string& scheme);
protected:
- explicit URLRequestHttpJob(net::URLRequest* request);
+ explicit URLRequestHttpJob(URLRequest* request);
- // URLRequestJob methods:
- virtual void SetUpload(net::UploadData* upload);
- virtual void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers);
+ // Overridden from URLRequestJob:
+ virtual void SetUpload(UploadData* upload);
+ virtual void SetExtraRequestHeaders(const HttpRequestHeaders& headers);
virtual void Start();
virtual void Kill();
- virtual net::LoadState GetLoadState() const;
+ virtual LoadState GetLoadState() const;
virtual uint64 GetUploadProgress() const;
virtual bool GetMimeType(std::string* mime_type) const;
virtual bool GetCharset(std::string* charset);
- virtual void GetResponseInfo(net::HttpResponseInfo* info);
+ virtual void GetResponseInfo(HttpResponseInfo* info);
virtual bool GetResponseCookies(std::vector<std::string>* cookies);
virtual int GetResponseCode() const;
virtual bool GetContentEncodings(
std::vector<Filter::FilterType>* encoding_type);
- virtual bool IsCachedContent() const { return is_cached_content_; }
+ virtual bool IsCachedContent() const;
virtual bool IsSdchResponse() const;
virtual bool IsSafeRedirect(const GURL& location);
virtual bool NeedsAuth();
- virtual void GetAuthChallengeInfo(scoped_refptr<net::AuthChallengeInfo>*);
+ virtual void GetAuthChallengeInfo(scoped_refptr<AuthChallengeInfo>*);
virtual void SetAuth(const string16& username,
const string16& password);
virtual void CancelAuth();
- virtual void ContinueWithCertificate(net::X509Certificate* client_cert);
+ virtual void ContinueWithCertificate(X509Certificate* client_cert);
virtual void ContinueDespiteLastError();
- virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
+ virtual bool ReadRawData(IOBuffer* buf, int buf_size, int *bytes_read);
virtual void StopCaching();
// Shadows URLRequestJob's version of this method so we can grab cookies.
@@ -69,7 +71,7 @@ class URLRequestHttpJob : public URLRequestJob {
void AddCookieHeaderAndStart();
void SaveCookiesAndNotifyHeadersComplete();
void SaveNextCookie();
- void FetchResponseCookies(const net::HttpResponseInfo* response_info,
+ void FetchResponseCookies(const HttpResponseInfo* response_info,
std::vector<std::string>* cookies);
// Process the Strict-Transport-Security header, if one exists.
@@ -89,33 +91,33 @@ class URLRequestHttpJob : public URLRequestJob {
// before us.
scoped_refptr<URLRequestContext> context_;
- net::HttpRequestInfo request_info_;
- const net::HttpResponseInfo* response_info_;
+ HttpRequestInfo request_info_;
+ const HttpResponseInfo* response_info_;
std::vector<std::string> response_cookies_;
size_t response_cookies_save_index_;
// Auth states for proxy and origin server.
- net::AuthState proxy_auth_state_;
- net::AuthState server_auth_state_;
+ AuthState proxy_auth_state_;
+ AuthState server_auth_state_;
string16 username_;
string16 password_;
- net::CompletionCallbackImpl<URLRequestHttpJob> can_get_cookies_callback_;
- net::CompletionCallbackImpl<URLRequestHttpJob> can_set_cookie_callback_;
- net::CompletionCallbackImpl<URLRequestHttpJob> start_callback_;
- net::CompletionCallbackImpl<URLRequestHttpJob> read_callback_;
+ CompletionCallbackImpl<URLRequestHttpJob> can_get_cookies_callback_;
+ CompletionCallbackImpl<URLRequestHttpJob> can_set_cookie_callback_;
+ CompletionCallbackImpl<URLRequestHttpJob> start_callback_;
+ CompletionCallbackImpl<URLRequestHttpJob> read_callback_;
bool read_in_progress_;
// An URL for an SDCH dictionary as suggested in a Get-Dictionary HTTP header.
GURL sdch_dictionary_url_;
- scoped_ptr<net::HttpTransaction> transaction_;
+ scoped_ptr<HttpTransaction> transaction_;
// This is used to supervise traffic and enforce exponential back-off.
- scoped_refptr<net::URLRequestThrottlerEntryInterface> throttling_entry_;
+ scoped_refptr<URLRequestThrottlerEntryInterface> throttling_entry_;
// Indicated if an SDCH dictionary was advertised, and hence an SDCH
// compressed response is expected. We use this to help detect (accidental?)
@@ -135,7 +137,11 @@ class URLRequestHttpJob : public URLRequestJob {
private:
virtual ~URLRequestHttpJob();
+ ScopedRunnableMethodFactory<URLRequestHttpJob> method_factory_;
+
DISALLOW_COPY_AND_ASSIGN(URLRequestHttpJob);
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_HTTP_JOB_H_
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index a059a00..0c54c10 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -21,6 +21,8 @@
using base::Time;
using base::TimeTicks;
+namespace net {
+
// Buffer size allocated when de-compressing data.
// static
const int URLRequestJob::kFilterBufSize = 32 * 1024;
@@ -443,7 +445,7 @@ void URLRequestJob::NotifyHeadersComplete() {
// Initialize to the current time, and let the subclass optionally override
// the time stamps if it has that information. The default request_time is
- // set by URLRequest before it calls our Start method.
+ // set by net::URLRequest before it calls our Start method.
request_->response_info_.response_time = Time::Now();
GetResponseInfo(&request_->response_info_);
@@ -930,3 +932,5 @@ void URLRequestJob::RecordCompressionHistograms() {
COMPRESSION_HISTOGRAM("NoProxy.ShouldHaveBeenCompressed", decompressed_B);
}
}
+
+} // namespace net
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 239f5e9..6f91c9a 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -17,20 +17,18 @@
#include "net/base/filter.h"
#include "net/base/load_states.h"
+class URLRequestStatus;
+
namespace net {
+
class AuthChallengeInfo;
class HttpRequestHeaders;
class HttpResponseInfo;
class IOBuffer;
-class UploadData;
class URLRequest;
-class X509Certificate;
-} // namespace net
-
-class URLRequestStatus;
class URLRequestJobMetrics;
-
-namespace net {
+class UploadData;
+class X509Certificate;
class URLRequestJob : public base::RefCounted<URLRequestJob>,
public FilterContext {
@@ -65,9 +63,9 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
// This function MUST somehow call NotifyDone/NotifyCanceled or some requests
// will get leaked. Certain callers use that message to know when they can
- // delete their URLRequest object, even when doing a cancel. The default Kill
- // implementation calls NotifyCanceled, so it is recommended that subclasses
- // call URLRequestJob::Kill() after doing any additional work.
+ // delete their net::URLRequest object, even when doing a cancel. The default
+ // Kill implementation calls NotifyCanceled, so it is recommended that
+ // subclasses call URLRequestJob::Kill() after doing any additional work.
//
// The job should endeavor to stop working as soon as is convenient, but must
// not send and complete notifications from inside this function. Instead,
@@ -90,12 +88,12 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
// Called to read post-filtered data from this Job, returning the number of
// bytes read, 0 when there is no more data, or -1 if there was an error.
- // This is just the backend for URLRequest::Read, see that function for more
- // info.
+ // This is just the backend for net::URLRequest::Read, see that function for
+ // more info.
bool Read(net::IOBuffer* buf, int buf_size, int* bytes_read);
// Stops further caching of this request, if any. For more info, see
- // URLRequest::StopCaching().
+ // net::URLRequest::StopCaching().
virtual void StopCaching();
// Called to fetch the current load state for the job.
@@ -157,8 +155,8 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
// Called to determine if it is okay to redirect this job to the specified
// location. This may be used to implement protocol-specific restrictions.
- // If this function returns false, then the URLRequest will fail reporting
- // net::ERR_UNSAFE_REDIRECT.
+ // If this function returns false, then the net::URLRequest will fail
+ // reporting net::ERR_UNSAFE_REDIRECT.
virtual bool IsSafeRedirect(const GURL& location);
// Called to determine if this response is asking for authentication. Only
@@ -240,8 +238,8 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
// that work.
void CompleteNotifyDone();
- // Used as an asynchronous callback for Kill to notify the URLRequest that
- // we were canceled.
+ // Used as an asynchronous callback for Kill to notify the net::URLRequest
+ // that we were canceled.
void NotifyCanceled();
// Notifies the job the request should be restarted.
@@ -256,7 +254,8 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
// If returning false, an error occurred or an async IO is now pending.
// If async IO is pending, the status of the request will be
// URLRequestStatus::IO_PENDING, and buf must remain available until the
- // operation is completed. See comments on URLRequest::Read for more info.
+ // operation is completed. See comments on net::URLRequest::Read for more
+ // info.
virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
// Informs the filter that data has been read into its buffer
@@ -298,9 +297,10 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
int prefilter_bytes_read_;
// The number of bytes read after passing through the filter.
int postfilter_bytes_read_;
- // True when (we believe) the content in this URLRequest was compressible.
+ // True when (we believe) the content in this net::URLRequest was
+ // compressible.
bool is_compressible_content_;
- // True when the content in this URLRequest was compressed.
+ // True when the content in this net::URLRequest was compressed.
bool is_compressed_;
private:
@@ -424,6 +424,4 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
} // namespace net
-typedef net::URLRequestJob URLRequestJob;
-
#endif // NET_URL_REQUEST_URL_REQUEST_JOB_H_
diff --git a/net/url_request/url_request_job_manager.cc b/net/url_request/url_request_job_manager.cc
index 225092b..9f08fd0 100644
--- a/net/url_request/url_request_job_manager.cc
+++ b/net/url_request/url_request_job_manager.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.
@@ -7,6 +7,7 @@
#include <algorithm>
#include "build/build_config.h"
+#include "base/singleton.h"
#include "base/string_util.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -22,11 +23,13 @@ namespace {
struct SchemeToFactory {
const char* scheme;
- URLRequest::ProtocolFactory* factory;
+ net::URLRequest::ProtocolFactory* factory;
};
} // namespace
+namespace net {
+
static const SchemeToFactory kBuiltinFactories[] = {
{ "http", URLRequestHttpJob::Factory },
{ "https", URLRequestHttpJob::Factory },
@@ -47,19 +50,25 @@ URLRequestJobManager::URLRequestJobManager() : enable_file_access_(false) {
URLRequestJobManager::~URLRequestJobManager() {}
-URLRequestJob* URLRequestJobManager::CreateJob(URLRequest* request) const {
+// static
+URLRequestJobManager* URLRequestJobManager::GetInstance() {
+ return Singleton<URLRequestJobManager>::get();
+}
+
+net::URLRequestJob* URLRequestJobManager::CreateJob(
+ net::URLRequest* request) const {
#ifndef NDEBUG
DCHECK(IsAllowedThread());
#endif
// If we are given an invalid URL, then don't even try to inspect the scheme.
if (!request->url().is_valid())
- return new URLRequestErrorJob(request, net::ERR_INVALID_URL);
+ return new net::URLRequestErrorJob(request, net::ERR_INVALID_URL);
// We do this here to avoid asking interceptors about unsupported schemes.
const std::string& scheme = request->url().scheme(); // already lowercase
if (!SupportsScheme(scheme))
- return new URLRequestErrorJob(request, net::ERR_UNKNOWN_URL_SCHEME);
+ return new net::URLRequestErrorJob(request, net::ERR_UNKNOWN_URL_SCHEME);
// THREAD-SAFETY NOTICE:
// We do not need to acquire the lock here since we are only reading our
@@ -69,7 +78,7 @@ URLRequestJob* URLRequestJobManager::CreateJob(URLRequest* request) const {
if (!(request->load_flags() & net::LOAD_DISABLE_INTERCEPT)) {
InterceptorList::const_iterator i;
for (i = interceptors_.begin(); i != interceptors_.end(); ++i) {
- URLRequestJob* job = (*i)->MaybeIntercept(request);
+ net::URLRequestJob* job = (*i)->MaybeIntercept(request);
if (job)
return job;
}
@@ -80,7 +89,7 @@ URLRequestJob* URLRequestJobManager::CreateJob(URLRequest* request) const {
// built-in protocol factory.
FactoryMap::const_iterator i = factories_.find(scheme);
if (i != factories_.end()) {
- URLRequestJob* job = i->second(request, scheme);
+ net::URLRequestJob* job = i->second(request, scheme);
if (job)
return job;
}
@@ -88,7 +97,7 @@ URLRequestJob* URLRequestJobManager::CreateJob(URLRequest* request) const {
// See if the request should be handled by a built-in protocol factory.
for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) {
if (scheme == kBuiltinFactories[i].scheme) {
- URLRequestJob* job = (kBuiltinFactories[i].factory)(request, scheme);
+ net::URLRequestJob* job = (kBuiltinFactories[i].factory)(request, scheme);
DCHECK(job); // The built-in factories are not expected to fail!
return job;
}
@@ -98,12 +107,12 @@ URLRequestJob* URLRequestJobManager::CreateJob(URLRequest* request) const {
// wasn't interested in handling the URL. That is fairly unexpected, and we
// don't know have a specific error to report here :-(
LOG(WARNING) << "Failed to map: " << request->url().spec();
- return new URLRequestErrorJob(request, net::ERR_FAILED);
+ return new net::URLRequestErrorJob(request, net::ERR_FAILED);
}
-URLRequestJob* URLRequestJobManager::MaybeInterceptRedirect(
- URLRequest* request,
- const GURL& location) const {
+net::URLRequestJob* URLRequestJobManager::MaybeInterceptRedirect(
+ net::URLRequest* request,
+ const GURL& location) const {
#ifndef NDEBUG
DCHECK(IsAllowedThread());
#endif
@@ -115,15 +124,15 @@ URLRequestJob* URLRequestJobManager::MaybeInterceptRedirect(
InterceptorList::const_iterator i;
for (i = interceptors_.begin(); i != interceptors_.end(); ++i) {
- URLRequestJob* job = (*i)->MaybeInterceptRedirect(request, location);
+ net::URLRequestJob* job = (*i)->MaybeInterceptRedirect(request, location);
if (job)
return job;
}
return NULL;
}
-URLRequestJob* URLRequestJobManager::MaybeInterceptResponse(
- URLRequest* request) const {
+net::URLRequestJob* URLRequestJobManager::MaybeInterceptResponse(
+ net::URLRequest* request) const {
#ifndef NDEBUG
DCHECK(IsAllowedThread());
#endif
@@ -135,7 +144,7 @@ URLRequestJob* URLRequestJobManager::MaybeInterceptResponse(
InterceptorList::const_iterator i;
for (i = interceptors_.begin(); i != interceptors_.end(); ++i) {
- URLRequestJob* job = (*i)->MaybeInterceptResponse(request);
+ net::URLRequestJob* job = (*i)->MaybeInterceptResponse(request);
if (job)
return job;
}
@@ -157,16 +166,16 @@ bool URLRequestJobManager::SupportsScheme(const std::string& scheme) const {
return false;
}
-URLRequest::ProtocolFactory* URLRequestJobManager::RegisterProtocolFactory(
+net::URLRequest::ProtocolFactory* URLRequestJobManager::RegisterProtocolFactory(
const std::string& scheme,
- URLRequest::ProtocolFactory* factory) {
+ net::URLRequest::ProtocolFactory* factory) {
#ifndef NDEBUG
DCHECK(IsAllowedThread());
#endif
AutoLock locked(lock_);
- URLRequest::ProtocolFactory* old_factory;
+ net::URLRequest::ProtocolFactory* old_factory;
FactoryMap::iterator i = factories_.find(scheme);
if (i != factories_.end()) {
old_factory = i->second;
@@ -182,7 +191,7 @@ URLRequest::ProtocolFactory* URLRequestJobManager::RegisterProtocolFactory(
}
void URLRequestJobManager::RegisterRequestInterceptor(
- URLRequest::Interceptor* interceptor) {
+ net::URLRequest::Interceptor* interceptor) {
#ifndef NDEBUG
DCHECK(IsAllowedThread());
#endif
@@ -195,7 +204,7 @@ void URLRequestJobManager::RegisterRequestInterceptor(
}
void URLRequestJobManager::UnregisterRequestInterceptor(
- URLRequest::Interceptor* interceptor) {
+ net::URLRequest::Interceptor* interceptor) {
#ifndef NDEBUG
DCHECK(IsAllowedThread());
#endif
@@ -207,3 +216,5 @@ void URLRequestJobManager::UnregisterRequestInterceptor(
DCHECK(i != interceptors_.end());
interceptors_.erase(i);
}
+
+} // namespace net
diff --git a/net/url_request/url_request_job_manager.h b/net/url_request/url_request_job_manager.h
index 0fbc31e..a0d3c87 100644
--- a/net/url_request/url_request_job_manager.h
+++ b/net/url_request/url_request_job_manager.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H__
-#define NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H__
+#ifndef NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_
+#define NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_
#pragma once
#include <map>
@@ -14,23 +14,27 @@
#include "base/platform_thread.h"
#include "net/url_request/url_request.h"
+template <typename T> struct DefaultSingletonTraits;
+
+namespace net {
+
// This class is responsible for managing the set of protocol factories and
-// request interceptors that determine how an URLRequestJob gets created to
-// handle an URLRequest.
+// request interceptors that determine how an net::URLRequestJob gets created to
+// handle an net::URLRequest.
//
// MULTI-THREADING NOTICE:
-// URLRequest is designed to have all consumers on a single thread, and so no
-// attempt is made to support ProtocolFactory or Interceptor instances being
-// registered/unregistered or in any way poked on multiple threads. However,
-// we do support checking for supported schemes FROM ANY THREAD (i.e., it is
-// safe to call SupportsScheme on any thread).
+// net::URLRequest is designed to have all consumers on a single thread, and
+// so no attempt is made to support ProtocolFactory or Interceptor instances
+// being registered/unregistered or in any way poked on multiple threads.
+// However, we do support checking for supported schemes FROM ANY THREAD
+// (i.e., it is safe to call SupportsScheme on any thread).
//
class URLRequestJobManager {
public:
- URLRequestJobManager();
- ~URLRequestJobManager();
+ // Returns the singleton instance.
+ static URLRequestJobManager* GetInstance();
- // Instantiate an URLRequestJob implementation based on the registered
+ // Instantiate an net::URLRequestJob implementation based on the registered
// interceptors and protocol factories. This will always succeed in
// returning a job unless we are--in the extreme case--out of memory.
net::URLRequestJob* CreateJob(net::URLRequest* request) const;
@@ -54,19 +58,23 @@ class URLRequestJobManager {
// Register a protocol factory associated with the given scheme. The factory
// parameter may be null to clear any existing association. Returns the
// previously registered protocol factory if any.
- URLRequest::ProtocolFactory* RegisterProtocolFactory(
- const std::string& scheme, URLRequest::ProtocolFactory* factory);
+ net::URLRequest::ProtocolFactory* RegisterProtocolFactory(
+ const std::string& scheme, net::URLRequest::ProtocolFactory* factory);
// Register/unregister a request interceptor.
- void RegisterRequestInterceptor(URLRequest::Interceptor* interceptor);
- void UnregisterRequestInterceptor(URLRequest::Interceptor* interceptor);
+ void RegisterRequestInterceptor(net::URLRequest::Interceptor* interceptor);
+ void UnregisterRequestInterceptor(net::URLRequest::Interceptor* interceptor);
void set_enable_file_access(bool enable) { enable_file_access_ = enable; }
bool enable_file_access() const { return enable_file_access_; }
private:
- typedef std::map<std::string, URLRequest::ProtocolFactory*> FactoryMap;
- typedef std::vector<URLRequest::Interceptor*> InterceptorList;
+ typedef std::map<std::string, net::URLRequest::ProtocolFactory*> FactoryMap;
+ typedef std::vector<net::URLRequest::Interceptor*> InterceptorList;
+ friend struct DefaultSingletonTraits<URLRequestJobManager>;
+
+ URLRequestJobManager();
+ ~URLRequestJobManager();
mutable Lock lock_;
FactoryMap factories_;
@@ -107,4 +115,6 @@ class URLRequestJobManager {
DISALLOW_COPY_AND_ASSIGN(URLRequestJobManager);
};
-#endif // NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H__
+} // namespace net
+
+#endif // NET_URL_REQUEST_URL_REQUEST_JOB_MANAGER_H_
diff --git a/net/url_request/url_request_job_metrics.cc b/net/url_request/url_request_job_metrics.cc
index fcaac74..87ef205 100644
--- a/net/url_request/url_request_job_metrics.cc
+++ b/net/url_request/url_request_job_metrics.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.
@@ -8,7 +8,7 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
-using base::TimeDelta;
+namespace net {
URLRequestJobMetrics::URLRequestJobMetrics()
: total_bytes_read_(0),
@@ -30,7 +30,7 @@ void URLRequestJobMetrics::AppendText(std::wstring* text) {
text->append(UTF8ToWide(url_->spec()));
}
- TimeDelta elapsed = end_time_ - start_time_;
+ base::TimeDelta elapsed = end_time_ - start_time_;
base::StringAppendF(text,
L"; total bytes read = %ld; read calls = %d; time = %lld ms;",
static_cast<long>(total_bytes_read_),
@@ -42,3 +42,5 @@ void URLRequestJobMetrics::AppendText(std::wstring* text) {
text->append(L" fail.");
}
}
+
+} // namespace net
diff --git a/net/url_request/url_request_job_metrics.h b/net/url_request/url_request_job_metrics.h
index ce0e4bf..15bbaf6 100644
--- a/net/url_request/url_request_job_metrics.h
+++ b/net/url_request/url_request_job_metrics.h
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Records IO statistics associated with a URLRequestJob.
+// Records IO statistics associated with a net::URLRequestJob.
// See description in navigation_profiler.h for an overview of perf profiling.
#ifndef NET_URL_REQUEST_URL_REQUEST_JOB_METRICS_H_
@@ -16,6 +16,8 @@
#include "base/time.h"
#include "googleurl/src/gurl.h"
+namespace net {
+
class URLRequestJobMetrics {
public:
URLRequestJobMetrics();
@@ -47,4 +49,6 @@ class URLRequestJobMetrics {
void AppendText(std::wstring* text);
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_JOB_METRICS_H_
diff --git a/net/url_request/url_request_job_tracker.cc b/net/url_request/url_request_job_tracker.cc
index e3e5d36..49472d9 100644
--- a/net/url_request/url_request_job_tracker.cc
+++ b/net/url_request/url_request_job_tracker.cc
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <algorithm>
-
#include "net/url_request/url_request_job_tracker.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "net/url_request/url_request_job.h"
+namespace net {
+
URLRequestJobTracker g_url_request_job_tracker;
URLRequestJobTracker::URLRequestJobTracker() {
@@ -16,9 +18,9 @@ URLRequestJobTracker::URLRequestJobTracker() {
URLRequestJobTracker::~URLRequestJobTracker() {
DLOG_IF(WARNING, active_jobs_.size() != 0) <<
- "Leaking " << active_jobs_.size() << " URLRequestJob object(s), this could "
- "be because the URLRequest forgot to free it (bad), or if the program was "
- "terminated while a request was active (normal).";
+ "Leaking " << active_jobs_.size() << " URLRequestJob object(s), this "
+ "could be because the URLRequest forgot to free it (bad), or if the "
+ "program was terminated while a request was active (normal).";
}
void URLRequestJobTracker::AddNewJob(URLRequestJob* job) {
@@ -56,3 +58,5 @@ void URLRequestJobTracker::OnBytesRead(URLRequestJob* job,
FOR_EACH_OBSERVER(JobObserver, observers_,
OnBytesRead(job, buf, byte_count));
}
+
+} // namespace net
diff --git a/net/url_request/url_request_job_tracker.h b/net/url_request/url_request_job_tracker.h
index cd0bd86..4c8ecec 100644
--- a/net/url_request/url_request_job_tracker.h
+++ b/net/url_request/url_request_job_tracker.h
@@ -11,40 +11,40 @@
#include "base/observer_list.h"
#include "net/url_request/url_request_status.h"
+class GURL;
+
namespace net {
class URLRequestJob;
-} // namespace net
-
-class GURL;
// This class maintains a list of active URLRequestJobs for debugging purposes.
// This allows us to warn on leaked jobs and also allows an observer to track
// what is happening, for example, for the network status monitor.
//
-// NOTE: URLRequest is single-threaded, so this class should only be used on
-// the same thread where all of the application's URLRequest calls are made.
+// NOTE: URLRequest is single-threaded, so this class should only be used
+// onthe same thread where all of the application's URLRequest calls are
+// made.
//
class URLRequestJobTracker {
public:
- typedef std::vector<net::URLRequestJob*> JobList;
+ typedef std::vector<URLRequestJob*> JobList;
typedef JobList::const_iterator JobIterator;
// The observer's methods are called on the thread that called AddObserver.
class JobObserver {
public:
// Called after the given job has been added to the list
- virtual void OnJobAdded(net::URLRequestJob* job) = 0;
+ virtual void OnJobAdded(URLRequestJob* job) = 0;
// Called after the given job has been removed from the list
- virtual void OnJobRemoved(net::URLRequestJob* job) = 0;
+ virtual void OnJobRemoved(URLRequestJob* job) = 0;
// Called when the given job has completed, before notifying the request
- virtual void OnJobDone(net::URLRequestJob* job,
+ virtual void OnJobDone(URLRequestJob* job,
const URLRequestStatus& status) = 0;
// Called when the given job is about to follow a redirect to the given
// new URL. The redirect type is given in status_code
- virtual void OnJobRedirect(net::URLRequestJob* job, const GURL& location,
+ virtual void OnJobRedirect(URLRequestJob* job, const GURL& location,
int status_code) = 0;
// Called when a new chunk of unfiltered bytes has been read for
@@ -52,7 +52,7 @@ class URLRequestJobTracker {
// read event only. |buf| is a pointer to the data buffer that
// contains those bytes. The data in |buf| is only valid for the
// duration of the OnBytesRead callback.
- virtual void OnBytesRead(net::URLRequestJob* job, const char* buf,
+ virtual void OnBytesRead(URLRequestJob* job, const char* buf,
int byte_count) = 0;
virtual ~JobObserver() {}
@@ -73,16 +73,16 @@ class URLRequestJobTracker {
// adds or removes the job from the active list, should be called by the
// job constructor and destructor. Note: don't use "AddJob" since that
// is #defined by windows.h :(
- void AddNewJob(net::URLRequestJob* job);
- void RemoveJob(net::URLRequestJob* job);
+ void AddNewJob(URLRequestJob* job);
+ void RemoveJob(URLRequestJob* job);
// Job status change notifications
- void OnJobDone(net::URLRequestJob* job, const URLRequestStatus& status);
- void OnJobRedirect(net::URLRequestJob* job, const GURL& location,
+ void OnJobDone(URLRequestJob* job, const URLRequestStatus& status);
+ void OnJobRedirect(URLRequestJob* job, const GURL& location,
int status_code);
// Bytes read notifications.
- void OnBytesRead(net::URLRequestJob* job, const char* buf, int byte_count);
+ void OnBytesRead(URLRequestJob* job, const char* buf, int byte_count);
// allows iteration over all active jobs
JobIterator begin() const {
@@ -99,4 +99,6 @@ class URLRequestJobTracker {
extern URLRequestJobTracker g_url_request_job_tracker;
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_JOB_TRACKER_H_
diff --git a/net/url_request/url_request_job_tracker_unittest.cc b/net/url_request/url_request_job_tracker_unittest.cc
index 3ddbcc2..bd62ef7 100644
--- a/net/url_request/url_request_job_tracker_unittest.cc
+++ b/net/url_request/url_request_job_tracker_unittest.cc
@@ -49,29 +49,29 @@ bool GetResponseBody(const GURL& url, std::string* out_body) {
return true;
}
-class MockJobObserver : public URLRequestJobTracker::JobObserver {
+class MockJobObserver : public net::URLRequestJobTracker::JobObserver {
public:
- MOCK_METHOD1(OnJobAdded, void(URLRequestJob* job));
- MOCK_METHOD1(OnJobRemoved, void(URLRequestJob* job));
- MOCK_METHOD2(OnJobDone, void(URLRequestJob* job,
+ MOCK_METHOD1(OnJobAdded, void(net::URLRequestJob* job));
+ MOCK_METHOD1(OnJobRemoved, void(net::URLRequestJob* job));
+ MOCK_METHOD2(OnJobDone, void(net::URLRequestJob* job,
const URLRequestStatus& status));
- MOCK_METHOD3(OnJobRedirect, void(URLRequestJob* job,
+ MOCK_METHOD3(OnJobRedirect, void(net::URLRequestJob* job,
const GURL& location,
int status_code));
- MOCK_METHOD3(OnBytesRead, void(URLRequestJob* job,
+ MOCK_METHOD3(OnBytesRead, void(net::URLRequestJob* job,
const char* buf,
int byte_count));
};
-// A URLRequestJob that returns static content for given URLs. We do
+// A net::URLRequestJob that returns static content for given URLs. We do
// not use URLRequestTestJob here because URLRequestTestJob fakes
// async operations by calling ReadRawData synchronously in an async
-// callback. This test requires a URLRequestJob that returns false for
+// callback. This test requires a net::URLRequestJob that returns false for
// async reads, in order to exercise the real async read codepath.
-class URLRequestJobTrackerTestJob : public URLRequestJob {
+class URLRequestJobTrackerTestJob : public net::URLRequestJob {
public:
- URLRequestJobTrackerTestJob(URLRequest* request, bool async_reads)
- : URLRequestJob(request), async_reads_(async_reads) {}
+ URLRequestJobTrackerTestJob(net::URLRequest* request, bool async_reads)
+ : net::URLRequestJob(request), async_reads_(async_reads) {}
void Start() {
ASSERT_TRUE(GetResponseBody(request_->url(), &response_data_));
@@ -125,7 +125,7 @@ class URLRequestJobTrackerTestJob : public URLRequestJob {
encoding_types->push_back(Filter::FILTER_TYPE_GZIP);
return true;
} else {
- return URLRequestJob::GetContentEncodings(encoding_types);
+ return net::URLRequestJob::GetContentEncodings(encoding_types);
}
}
@@ -151,7 +151,7 @@ MATCHER_P2(MemEq, other, len, "") {
class URLRequestJobTrackerTest : public PlatformTest {
protected:
static void SetUpTestCase() {
- URLRequest::RegisterProtocolFactory("test", &Factory);
+ net::URLRequest::RegisterProtocolFactory("test", &Factory);
}
virtual void SetUp() {
@@ -176,15 +176,15 @@ class URLRequestJobTrackerTest : public PlatformTest {
EXPECT_CALL(observer, OnJobRemoved(NotNull()));
// Attach our observer and perform the resource fetch.
- g_url_request_job_tracker.AddObserver(&observer);
+ net::g_url_request_job_tracker.AddObserver(&observer);
Fetch(gurl);
- g_url_request_job_tracker.RemoveObserver(&observer);
+ net::g_url_request_job_tracker.RemoveObserver(&observer);
}
void Fetch(const GURL& url) {
TestDelegate d;
{
- URLRequest request(url, &d);
+ net::URLRequest request(url, &d);
request.Start();
MessageLoop::current()->RunAllPending();
}
@@ -196,13 +196,14 @@ class URLRequestJobTrackerTest : public PlatformTest {
EXPECT_STREQ(kBasic, d.data_received().c_str());
}
- static URLRequest::ProtocolFactory Factory;
+ static net::URLRequest::ProtocolFactory Factory;
static bool g_async_reads;
};
// static
-URLRequestJob* URLRequestJobTrackerTest::Factory(URLRequest* request,
- const std::string& scheme) {
+net::URLRequestJob* URLRequestJobTrackerTest::Factory(
+ net::URLRequest* request,
+ const std::string& scheme) {
return new URLRequestJobTrackerTestJob(request, g_async_reads);
}
diff --git a/net/url_request/url_request_netlog_params.cc b/net/url_request/url_request_netlog_params.cc
index 56414b1..42076bc 100644
--- a/net/url_request/url_request_netlog_params.cc
+++ b/net/url_request/url_request_netlog_params.cc
@@ -6,11 +6,13 @@
#include "base/values.h"
+namespace net {
+
URLRequestStartEventParameters::URLRequestStartEventParameters(
const GURL& url,
const std::string& method,
int load_flags,
- net::RequestPriority priority)
+ RequestPriority priority)
: url_(url),
method_(method),
load_flags_(load_flags),
@@ -25,3 +27,5 @@ Value* URLRequestStartEventParameters::ToValue() const {
dict->SetInteger("priority", static_cast<int>(priority_));
return dict;
}
+
+} // namespace net
diff --git a/net/url_request/url_request_netlog_params.h b/net/url_request/url_request_netlog_params.h
index 12bd1f1..8b275b9 100644
--- a/net/url_request/url_request_netlog_params.h
+++ b/net/url_request/url_request_netlog_params.h
@@ -13,13 +13,15 @@
#include "net/base/net_log.h"
#include "net/base/request_priority.h"
+namespace net {
+
// Holds the parameters to emit to the NetLog when starting a URLRequest.
-class URLRequestStartEventParameters : public net::NetLog::EventParameters {
+class URLRequestStartEventParameters : public NetLog::EventParameters {
public:
URLRequestStartEventParameters(const GURL& url,
const std::string& method,
int load_flags,
- net::RequestPriority priority);
+ RequestPriority priority);
const GURL& url() const {
return url_;
@@ -35,9 +37,11 @@ class URLRequestStartEventParameters : public net::NetLog::EventParameters {
const GURL url_;
const std::string method_;
const int load_flags_;
- const net::RequestPriority priority_;
+ const RequestPriority priority_;
DISALLOW_COPY_AND_ASSIGN(URLRequestStartEventParameters);
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_NETLOG_PARAMS_H_
diff --git a/net/url_request/url_request_redirect_job.cc b/net/url_request/url_request_redirect_job.cc
index 001da10..9c5605a 100644
--- a/net/url_request/url_request_redirect_job.cc
+++ b/net/url_request/url_request_redirect_job.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.
@@ -6,7 +6,9 @@
#include "base/message_loop.h"
-URLRequestRedirectJob::URLRequestRedirectJob(net::URLRequest* request,
+namespace net {
+
+URLRequestRedirectJob::URLRequestRedirectJob(URLRequest* request,
GURL redirect_destination)
: URLRequestJob(request), redirect_destination_(redirect_destination) {
}
@@ -16,10 +18,6 @@ void URLRequestRedirectJob::Start() {
this, &URLRequestRedirectJob::StartAsync));
}
-void URLRequestRedirectJob::StartAsync() {
- NotifyHeadersComplete();
-}
-
bool URLRequestRedirectJob::IsRedirectResponse(GURL* location,
int* http_status_code) {
*location = redirect_destination_;
@@ -27,3 +25,10 @@ bool URLRequestRedirectJob::IsRedirectResponse(GURL* location,
return true;
}
+URLRequestRedirectJob::~URLRequestRedirectJob() {}
+
+void URLRequestRedirectJob::StartAsync() {
+ NotifyHeadersComplete();
+}
+
+} // namespace net
diff --git a/net/url_request/url_request_redirect_job.h b/net/url_request/url_request_redirect_job.h
index 7466cec..425c70b 100644
--- a/net/url_request/url_request_redirect_job.h
+++ b/net/url_request/url_request_redirect_job.h
@@ -10,23 +10,27 @@
class GURL;
+namespace net {
+
// A URLRequestJob that will redirect the request to the specified
// URL. This is useful to restart a request at a different URL based
// on the result of another job.
class URLRequestRedirectJob : public URLRequestJob {
public:
// Constructs a job that redirects to the specified URL.
- URLRequestRedirectJob(net::URLRequest* request, GURL redirect_destination);
+ URLRequestRedirectJob(URLRequest* request, GURL redirect_destination);
virtual void Start();
- bool IsRedirectResponse(GURL* location, int* http_status_code);
+ virtual bool IsRedirectResponse(GURL* location, int* http_status_code);
private:
- ~URLRequestRedirectJob() {}
+ virtual ~URLRequestRedirectJob();
void StartAsync();
GURL redirect_destination_;
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_REDIRECT_JOB_H_
diff --git a/net/url_request/url_request_simple_job.cc b/net/url_request/url_request_simple_job.cc
index 38e0c4d..0b95d38 100644
--- a/net/url_request/url_request_simple_job.cc
+++ b/net/url_request/url_request_simple_job.cc
@@ -9,7 +9,9 @@
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"
-URLRequestSimpleJob::URLRequestSimpleJob(net::URLRequest* request)
+namespace net {
+
+URLRequestSimpleJob::URLRequestSimpleJob(URLRequest* request)
: URLRequestJob(request),
data_offset_(0) {
}
@@ -31,7 +33,7 @@ bool URLRequestSimpleJob::GetCharset(std::string* charset) {
return true;
}
-bool URLRequestSimpleJob::ReadRawData(net::IOBuffer* buf, int buf_size,
+bool URLRequestSimpleJob::ReadRawData(IOBuffer* buf, int buf_size,
int* bytes_read) {
DCHECK(bytes_read);
int remaining = static_cast<int>(data_.size()) - data_offset_;
@@ -53,6 +55,8 @@ void URLRequestSimpleJob::StartAsync() {
} else {
// what should the error code be?
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
- net::ERR_INVALID_URL));
+ ERR_INVALID_URL));
}
}
+
+} // namespace net
diff --git a/net/url_request/url_request_simple_job.h b/net/url_request/url_request_simple_job.h
index 877b081..7b48adb 100644
--- a/net/url_request/url_request_simple_job.h
+++ b/net/url_request/url_request_simple_job.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.
@@ -11,15 +11,15 @@
#include "net/url_request/url_request_job.h"
namespace net {
+
class URLRequest;
-} // namespace net
-class URLRequestSimpleJob : public net::URLRequestJob {
+class URLRequestSimpleJob : public URLRequestJob {
public:
- explicit URLRequestSimpleJob(net::URLRequest* request);
+ explicit URLRequestSimpleJob(URLRequest* request);
virtual void Start();
- virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
+ virtual bool ReadRawData(IOBuffer* buf, int buf_size, int *bytes_read);
virtual bool GetMimeType(std::string* mime_type) const;
virtual bool GetCharset(std::string* charset);
@@ -41,4 +41,6 @@ class URLRequestSimpleJob : public net::URLRequestJob {
int data_offset_;
};
+} // namespace net
+
#endif // NET_URL_REQUEST_URL_REQUEST_SIMPLE_JOB_H_
diff --git a/net/url_request/url_request_test_job.cc b/net/url_request/url_request_test_job.cc
index 363d178..7fd019c 100644
--- a/net/url_request/url_request_test_job.cc
+++ b/net/url_request/url_request_test_job.cc
@@ -70,13 +70,13 @@ std::string URLRequestTestJob::test_error_headers() {
}
// static
-URLRequestJob* URLRequestTestJob::Factory(URLRequest* request,
- const std::string& scheme) {
+net::URLRequestJob* URLRequestTestJob::Factory(net::URLRequest* request,
+ const std::string& scheme) {
return new URLRequestTestJob(request);
}
-URLRequestTestJob::URLRequestTestJob(URLRequest* request)
- : URLRequestJob(request),
+URLRequestTestJob::URLRequestTestJob(net::URLRequest* request)
+ : net::URLRequestJob(request),
auto_advance_(false),
stage_(WAITING),
offset_(0),
@@ -84,8 +84,9 @@ URLRequestTestJob::URLRequestTestJob(URLRequest* request)
async_buf_size_(0) {
}
-URLRequestTestJob::URLRequestTestJob(URLRequest* request, bool auto_advance)
- : URLRequestJob(request),
+URLRequestTestJob::URLRequestTestJob(net::URLRequest* request,
+ bool auto_advance)
+ : net::URLRequestJob(request),
auto_advance_(auto_advance),
stage_(WAITING),
offset_(0),
@@ -93,11 +94,11 @@ URLRequestTestJob::URLRequestTestJob(URLRequest* request, bool auto_advance)
async_buf_size_(0) {
}
-URLRequestTestJob::URLRequestTestJob(URLRequest* request,
+URLRequestTestJob::URLRequestTestJob(net::URLRequest* request,
const std::string& response_headers,
const std::string& response_data,
bool auto_advance)
- : URLRequestJob(request),
+ : net::URLRequestJob(request),
auto_advance_(auto_advance),
stage_(WAITING),
response_headers_(new net::HttpResponseHeaders(response_headers)),
@@ -206,7 +207,7 @@ bool URLRequestTestJob::IsRedirectResponse(GURL* location,
void URLRequestTestJob::Kill() {
stage_ = DONE;
- URLRequestJob::Kill();
+ net::URLRequestJob::Kill();
}
void URLRequestTestJob::ProcessNextOperation() {
diff --git a/net/url_request/url_request_test_job.h b/net/url_request/url_request_test_job.h
index 14b90d4..ec92dc2 100644
--- a/net/url_request/url_request_test_job.h
+++ b/net/url_request/url_request_test_job.h
@@ -37,16 +37,16 @@ class URLRequestTestJob : public net::URLRequestJob {
public:
// Constructs a job to return one of the canned responses depending on the
// request url, with auto advance disabled.
- explicit URLRequestTestJob(URLRequest* request);
+ explicit URLRequestTestJob(net::URLRequest* request);
// Constructs a job to return one of the canned responses depending on the
// request url, optionally with auto advance enabled.
- explicit URLRequestTestJob(URLRequest* request, bool auto_advance);
+ explicit URLRequestTestJob(net::URLRequest* request, bool auto_advance);
// Constructs a job to return the given response regardless of the request
// url. The headers should include the HTTP status line and be formatted as
// expected by net::HttpResponseHeaders.
- explicit URLRequestTestJob(URLRequest* request,
+ explicit URLRequestTestJob(net::URLRequest* request,
const std::string& response_headers,
const std::string& response_data,
bool auto_advance);
@@ -86,7 +86,7 @@ class URLRequestTestJob : public net::URLRequestJob {
void set_auto_advance(bool auto_advance) { auto_advance_ = auto_advance; }
// Factory method for protocol factory registration if callers don't subclass
- static URLRequest::ProtocolFactory Factory;
+ static net::URLRequest::ProtocolFactory Factory;
// Job functions
virtual void Start();
diff --git a/net/url_request/url_request_throttler_entry.h b/net/url_request/url_request_throttler_entry.h
index 9b8955d..ac33fa1 100644
--- a/net/url_request/url_request_throttler_entry.h
+++ b/net/url_request/url_request_throttler_entry.h
@@ -18,8 +18,8 @@ namespace net {
// deduce the back-off time for every request.
// The back-off algorithm consists of two parts. Firstly, exponential back-off
// is used when receiving 5XX server errors or malformed response bodies.
-// The exponential back-off rule is enforced by URLRequestHttpJob. Any request
-// sent during the back-off period will be cancelled.
+// The exponential back-off rule is enforced by URLRequestHttpJob. Any
+// request sent during the back-off period will be cancelled.
// Secondly, a sliding window is used to count recent requests to a given
// destination and provide guidance (to the application level only) on whether
// too many requests have been sent and when a good time to send the next one
diff --git a/net/url_request/url_request_throttler_entry_interface.h b/net/url_request/url_request_throttler_entry_interface.h
index f443b29..ed3c17f 100644
--- a/net/url_request/url_request_throttler_entry_interface.h
+++ b/net/url_request/url_request_throttler_entry_interface.h
@@ -21,8 +21,8 @@ class URLRequestThrottlerEntryInterface
// Returns true when we have encountered server errors and are doing
// exponential back-off.
- // URLRequestHttpJob checks this method prior to every request; it cancels
- // requests if this method returns true.
+ // net::URLRequestHttpJob checks this method prior to every request; it
+ // cancels requests if this method returns true.
virtual bool IsDuringExponentialBackoff() const = 0;
// Calculates a recommended sending time for the next request and reserves it.
diff --git a/net/url_request/url_request_throttler_header_adapter.cc b/net/url_request/url_request_throttler_header_adapter.cc
index e453071..368d6fe 100644
--- a/net/url_request/url_request_throttler_header_adapter.cc
+++ b/net/url_request/url_request_throttler_header_adapter.cc
@@ -13,6 +13,8 @@ URLRequestThrottlerHeaderAdapter::URLRequestThrottlerHeaderAdapter(
: response_header_(headers) {
}
+URLRequestThrottlerHeaderAdapter::~URLRequestThrottlerHeaderAdapter() {}
+
std::string URLRequestThrottlerHeaderAdapter::GetNormalizedValue(
const std::string& key) const {
std::string return_value;
diff --git a/net/url_request/url_request_throttler_header_adapter.h b/net/url_request/url_request_throttler_header_adapter.h
index 599a9f6..35d363e 100644
--- a/net/url_request/url_request_throttler_header_adapter.h
+++ b/net/url_request/url_request_throttler_header_adapter.h
@@ -19,7 +19,7 @@ class URLRequestThrottlerHeaderAdapter
: public URLRequestThrottlerHeaderInterface {
public:
explicit URLRequestThrottlerHeaderAdapter(net::HttpResponseHeaders* headers);
- virtual ~URLRequestThrottlerHeaderAdapter() {}
+ virtual ~URLRequestThrottlerHeaderAdapter();
// Implementation of URLRequestThrottlerHeaderInterface
virtual std::string GetNormalizedValue(const std::string& key) const;
diff --git a/net/url_request/url_request_throttler_manager.cc b/net/url_request/url_request_throttler_manager.cc
index 5428d9a..04e05c9 100644
--- a/net/url_request/url_request_throttler_manager.cc
+++ b/net/url_request/url_request_throttler_manager.cc
@@ -32,7 +32,8 @@ scoped_refptr<URLRequestThrottlerEntryInterface>
}
URLRequestThrottlerManager::URLRequestThrottlerManager()
- : requests_since_last_gc_(0) {
+ : requests_since_last_gc_(0),
+ enforce_throttling_(true) {
}
URLRequestThrottlerManager::~URLRequestThrottlerManager() {
diff --git a/net/url_request/url_request_throttler_manager.h b/net/url_request/url_request_throttler_manager.h
index 6c8cd2f..98211d9 100644
--- a/net/url_request/url_request_throttler_manager.h
+++ b/net/url_request/url_request_throttler_manager.h
@@ -49,6 +49,12 @@ class URLRequestThrottlerManager {
// It is only used by unit tests.
void EraseEntryForTests(const GURL& url);
+ void set_enforce_throttling(bool enforce_throttling) {
+ enforce_throttling_ = enforce_throttling;
+ }
+
+ bool enforce_throttling() const { return enforce_throttling_; }
+
protected:
URLRequestThrottlerManager();
~URLRequestThrottlerManager();
@@ -93,6 +99,10 @@ class URLRequestThrottlerManager {
mutable scoped_ptr<GURL::Replacements> url_id_replacements_;
+ // Whether we would like to reject outgoing HTTP requests during the back-off
+ // period.
+ bool enforce_throttling_;
+
DISALLOW_COPY_AND_ASSIGN(URLRequestThrottlerManager);
};
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 2c44a1c..4be2ec5 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -119,7 +119,7 @@ void CheckSSLInfo(const net::SSLInfo& ssl_info) {
class URLRequestTest : public PlatformTest {
public:
static void SetUpTestCase() {
- URLRequest::AllowFileAccess();
+ net::URLRequest::AllowFileAccess();
}
};
@@ -154,7 +154,7 @@ class URLRequestTestHTTP : public URLRequestTest {
for (int i = 0; i < kIterations; ++i) {
TestDelegate d;
- URLRequest r(test_server_.GetURL("echo"), &d);
+ net::URLRequest r(test_server_.GetURL("echo"), &d);
r.set_context(context);
r.set_method(method.c_str());
@@ -188,7 +188,7 @@ TEST_F(URLRequestTestHTTP, ProxyTunnelRedirectTest) {
TestDelegate d;
{
- URLRequest r(GURL("https://www.redirect.com/"), &d);
+ net::URLRequest r(GURL("https://www.redirect.com/"), &d);
r.set_context(
new TestURLRequestContext(test_server_.host_port_pair().ToString()));
@@ -213,7 +213,7 @@ TEST_F(URLRequestTestHTTP, UnexpectedServerAuthTest) {
TestDelegate d;
{
- URLRequest r(GURL("https://www.server-auth.com/"), &d);
+ net::URLRequest r(GURL("https://www.server-auth.com/"), &d);
r.set_context(
new TestURLRequestContext(test_server_.host_port_pair().ToString()));
@@ -386,7 +386,7 @@ class SSLClientAuthTestDelegate : public TestDelegate {
SSLClientAuthTestDelegate() : on_certificate_requested_count_(0) {
}
virtual void OnCertificateRequested(
- URLRequest* request,
+ net::URLRequest* request,
net::SSLCertRequestInfo* cert_request_info) {
on_certificate_requested_count_++;
MessageLoop::current()->Quit();
@@ -536,7 +536,7 @@ TEST_F(URLRequestTestHTTP, CancelTest5) {
// populate cache
{
TestDelegate d;
- URLRequest r(test_server_.GetURL("cachetime"), &d);
+ net::URLRequest r(test_server_.GetURL("cachetime"), &d);
r.set_context(context);
r.Start();
MessageLoop::current()->Run();
@@ -546,7 +546,7 @@ TEST_F(URLRequestTestHTTP, CancelTest5) {
// cancel read from cache (see bug 990242)
{
TestDelegate d;
- URLRequest r(test_server_.GetURL("cachetime"), &d);
+ net::URLRequest r(test_server_.GetURL("cachetime"), &d);
r.set_context(context);
r.Start();
r.Cancel();
@@ -1143,7 +1143,7 @@ TEST_F(URLRequestTestHTTP, VaryHeader) {
// populate the cache
{
TestDelegate d;
- URLRequest req(test_server_.GetURL("echoheader?foo"), &d);
+ net::URLRequest req(test_server_.GetURL("echoheader?foo"), &d);
req.set_context(context);
net::HttpRequestHeaders headers;
headers.SetHeader("foo", "1");
@@ -1155,7 +1155,7 @@ TEST_F(URLRequestTestHTTP, VaryHeader) {
// expect a cache hit
{
TestDelegate d;
- URLRequest req(test_server_.GetURL("echoheader?foo"), &d);
+ net::URLRequest req(test_server_.GetURL("echoheader?foo"), &d);
req.set_context(context);
net::HttpRequestHeaders headers;
headers.SetHeader("foo", "1");
@@ -1169,7 +1169,7 @@ TEST_F(URLRequestTestHTTP, VaryHeader) {
// expect a cache miss
{
TestDelegate d;
- URLRequest req(test_server_.GetURL("echoheader?foo"), &d);
+ net::URLRequest req(test_server_.GetURL("echoheader?foo"), &d);
req.set_context(context);
net::HttpRequestHeaders headers;
headers.SetHeader("foo", "2");
@@ -1192,7 +1192,7 @@ TEST_F(URLRequestTestHTTP, BasicAuth) {
d.set_username(kUser);
d.set_password(kSecret);
- URLRequest r(test_server_.GetURL("auth-basic"), &d);
+ net::URLRequest r(test_server_.GetURL("auth-basic"), &d);
r.set_context(context);
r.Start();
@@ -1209,7 +1209,7 @@ TEST_F(URLRequestTestHTTP, BasicAuth) {
d.set_username(kUser);
d.set_password(kSecret);
- URLRequest r(test_server_.GetURL("auth-basic"), &d);
+ net::URLRequest r(test_server_.GetURL("auth-basic"), &d);
r.set_context(context);
r.set_load_flags(net::LOAD_VALIDATE_CACHE);
r.Start();
@@ -1239,7 +1239,7 @@ TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
d.set_username(kUser);
d.set_password(kSecret);
- URLRequest r(url_requiring_auth, &d);
+ net::URLRequest r(url_requiring_auth, &d);
r.set_context(context);
r.Start();
@@ -1265,7 +1265,7 @@ TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
replacements.SetPasswordStr(password);
GURL url_with_identity = url_requiring_auth.ReplaceComponents(replacements);
- URLRequest r(url_with_identity, &d);
+ net::URLRequest r(url_with_identity, &d);
r.set_context(context);
r.Start();
@@ -1288,7 +1288,7 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"), &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"), &d);
req.set_context(context);
req.Start();
MessageLoop::current()->Run();
@@ -1337,8 +1337,8 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
- &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
+ &d);
req.set_context(context);
req.Start();
MessageLoop::current()->Run();
@@ -1351,7 +1351,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
// Try to set-up another cookie and update the previous cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL(
+ net::URLRequest req(test_server.GetURL(
"set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), &d);
req.set_load_flags(net::LOAD_DO_NOT_SAVE_COOKIES);
req.set_context(context);
@@ -1393,7 +1393,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"), &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"), &d);
req.set_context(context);
req.Start();
MessageLoop::current()->Run();
@@ -1447,8 +1447,8 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
- &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
+ &d);
req.set_context(context);
req.Start();
MessageLoop::current()->Run();
@@ -1463,7 +1463,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
context->set_cookie_policy(&cookie_policy);
TestDelegate d;
- URLRequest req(test_server.GetURL(
+ net::URLRequest req(test_server.GetURL(
"set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), &d);
req.set_context(context);
req.Start();
@@ -1504,7 +1504,7 @@ TEST_F(URLRequestTest, DoNotSaveEmptyCookies) {
// Set up an empty cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie"), &d);
+ net::URLRequest req(test_server.GetURL("set-cookie"), &d);
req.set_context(context);
req.Start();
MessageLoop::current()->Run();
@@ -1524,7 +1524,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"), &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"), &d);
req.set_context(context);
req.Start();
MessageLoop::current()->Run();
@@ -1579,8 +1579,8 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
- &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
+ &d);
req.set_context(context);
req.Start();
MessageLoop::current()->Run();
@@ -1596,7 +1596,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
context->set_cookie_policy(&cookie_policy);
TestDelegate d;
- URLRequest req(test_server.GetURL(
+ net::URLRequest req(test_server.GetURL(
"set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"), &d);
req.set_context(context);
req.Start();
@@ -1639,8 +1639,8 @@ TEST_F(URLRequestTest, CancelTest_During_CookiePolicy) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie?A=1&B=2&C=3"),
- &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?A=1&B=2&C=3"),
+ &d);
req.set_context(context);
req.Start(); // Triggers an asynchronous cookie policy check.
@@ -1654,7 +1654,7 @@ TEST_F(URLRequestTest, CancelTest_During_CookiePolicy) {
context->set_cookie_policy(NULL);
// Let the cookie policy complete. Make sure it handles the destruction of
- // the URLRequest properly.
+ // the net::URLRequest properly.
MessageLoop::current()->RunAllPending();
}
@@ -1671,8 +1671,8 @@ TEST_F(URLRequestTest, CancelTest_During_OnGetCookies) {
{
TestDelegate d;
d.set_cancel_in_get_cookies_blocked(true);
- URLRequest req(test_server.GetURL("set-cookie?A=1&B=2&C=3"),
- &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?A=1&B=2&C=3"),
+ &d);
req.set_context(context);
req.Start(); // Triggers an asynchronous cookie policy check.
@@ -1700,8 +1700,8 @@ TEST_F(URLRequestTest, CancelTest_During_OnSetCookie) {
{
TestDelegate d;
d.set_cancel_in_set_cookie_blocked(true);
- URLRequest req(test_server.GetURL("set-cookie?A=1&B=2&C=3"),
- &d);
+ net::URLRequest req(test_server.GetURL("set-cookie?A=1&B=2&C=3"),
+ &d);
req.set_context(context);
req.Start(); // Triggers an asynchronous cookie policy check.
@@ -1733,7 +1733,7 @@ TEST_F(URLRequestTest, CookiePolicy_ForceSession) {
// Set up a cookie.
{
TestDelegate d;
- URLRequest req(test_server.GetURL(
+ net::URLRequest req(test_server.GetURL(
"set-cookie?A=1;expires=\"Fri, 05 Feb 2010 23:42:01 GMT\""), &d);
req.set_context(context);
req.Start(); // Triggers an asynchronous cookie policy check.
@@ -1745,7 +1745,7 @@ TEST_F(URLRequestTest, CookiePolicy_ForceSession) {
}
// Now, check the cookie store.
- net::CookieMonster::CookieList cookies =
+ net::CookieList cookies =
context->cookie_store()->GetCookieMonster()->GetAllCookies();
EXPECT_EQ(1U, cookies.size());
EXPECT_FALSE(cookies[0].IsPersistent());
@@ -1822,7 +1822,7 @@ TEST_F(URLRequestTestHTTP, Post307RedirectPost) {
// Custom URLRequestJobs for use with interceptor tests
class RestartTestJob : public URLRequestTestJob {
public:
- explicit RestartTestJob(URLRequest* request)
+ explicit RestartTestJob(net::URLRequest* request)
: URLRequestTestJob(request, true) {}
protected:
virtual void StartAsync() {
@@ -1834,7 +1834,7 @@ class RestartTestJob : public URLRequestTestJob {
class CancelTestJob : public URLRequestTestJob {
public:
- explicit CancelTestJob(URLRequest* request)
+ explicit CancelTestJob(net::URLRequest* request)
: URLRequestTestJob(request, true) {}
protected:
virtual void StartAsync() {
@@ -1846,7 +1846,7 @@ class CancelTestJob : public URLRequestTestJob {
class CancelThenRestartTestJob : public URLRequestTestJob {
public:
- explicit CancelThenRestartTestJob(URLRequest* request)
+ explicit CancelThenRestartTestJob(net::URLRequest* request)
: URLRequestTestJob(request, true) {
}
protected:
@@ -1859,7 +1859,7 @@ class CancelThenRestartTestJob : public URLRequestTestJob {
};
// An Interceptor for use with interceptor tests
-class TestInterceptor : URLRequest::Interceptor {
+class TestInterceptor : net::URLRequest::Interceptor {
public:
TestInterceptor()
: intercept_main_request_(false), restart_main_request_(false),
@@ -1872,14 +1872,14 @@ class TestInterceptor : URLRequest::Interceptor {
did_simulate_error_main_(false),
did_intercept_redirect_(false), did_cancel_redirect_(false),
did_intercept_final_(false), did_cancel_final_(false) {
- URLRequest::RegisterRequestInterceptor(this);
+ net::URLRequest::RegisterRequestInterceptor(this);
}
~TestInterceptor() {
- URLRequest::UnregisterRequestInterceptor(this);
+ net::URLRequest::UnregisterRequestInterceptor(this);
}
- virtual URLRequestJob* MaybeIntercept(URLRequest* request) {
+ virtual net::URLRequestJob* MaybeIntercept(net::URLRequest* request) {
if (restart_main_request_) {
restart_main_request_ = false;
did_restart_main_ = true;
@@ -1911,8 +1911,8 @@ class TestInterceptor : URLRequest::Interceptor {
true);
}
- virtual URLRequestJob* MaybeInterceptRedirect(URLRequest* request,
- const GURL& location) {
+ virtual net::URLRequestJob* MaybeInterceptRedirect(net::URLRequest* request,
+ const GURL& location) {
if (cancel_redirect_request_) {
cancel_redirect_request_ = false;
did_cancel_redirect_ = true;
@@ -1928,7 +1928,7 @@ class TestInterceptor : URLRequest::Interceptor {
true);
}
- virtual URLRequestJob* MaybeInterceptResponse(URLRequest* request) {
+ virtual net::URLRequestJob* MaybeInterceptResponse(net::URLRequest* request) {
if (cancel_final_request_) {
cancel_final_request_ = false;
did_cancel_final_ = true;
@@ -2019,9 +2019,9 @@ TEST_F(URLRequestTest, Intercept) {
TestDelegate d;
TestURLRequest req(GURL("http://test_intercept/foo"), &d);
- URLRequest::UserData* user_data0 = new URLRequest::UserData();
- URLRequest::UserData* user_data1 = new URLRequest::UserData();
- URLRequest::UserData* user_data2 = new URLRequest::UserData();
+ net::URLRequest::UserData* user_data0 = new net::URLRequest::UserData();
+ net::URLRequest::UserData* user_data1 = new net::URLRequest::UserData();
+ net::URLRequest::UserData* user_data2 = new net::URLRequest::UserData();
req.SetUserData(NULL, user_data0);
req.SetUserData(&user_data1, user_data1);
req.SetUserData(&user_data2, user_data2);
diff --git a/net/url_request/url_request_unittest.h b/net/url_request/url_request_unittest.h
index af8f49e..50236fd 100644
--- a/net/url_request/url_request_unittest.h
+++ b/net/url_request/url_request_unittest.h
@@ -20,6 +20,7 @@
#include "base/thread.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
+#include "net/base/cert_verifier.h"
#include "net/base/cookie_monster.h"
#include "net/base/cookie_policy.h"
#include "net/base/host_resolver.h"
@@ -150,17 +151,20 @@ class TestURLRequestContext : public URLRequestContext {
delete ftp_transaction_factory_;
delete http_transaction_factory_;
delete http_auth_handler_factory_;
+ delete cert_verifier_;
delete host_resolver_;
}
private:
void Init() {
+ cert_verifier_ = new net::CertVerifier;
ftp_transaction_factory_ = new net::FtpNetworkLayer(host_resolver_);
ssl_config_service_ = new net::SSLConfigServiceDefaults;
http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
host_resolver_);
http_transaction_factory_ = new net::HttpCache(
net::HttpNetworkLayer::CreateFactory(host_resolver_,
+ cert_verifier_,
NULL /* dnsrr_resolver */,
NULL /* dns_cert_checker */,
NULL /* ssl_host_info_factory */,
@@ -179,17 +183,17 @@ class TestURLRequestContext : public URLRequestContext {
//-----------------------------------------------------------------------------
-class TestURLRequest : public URLRequest {
+class TestURLRequest : public net::URLRequest {
public:
TestURLRequest(const GURL& url, Delegate* delegate)
- : URLRequest(url, delegate) {
+ : net::URLRequest(url, delegate) {
set_context(new TestURLRequestContext());
}
};
//-----------------------------------------------------------------------------
-class TestDelegate : public URLRequest::Delegate {
+class TestDelegate : public net::URLRequest::Delegate {
public:
TestDelegate()
: cancel_in_rr_(false),
@@ -213,7 +217,7 @@ class TestDelegate : public URLRequest::Delegate {
buf_(new net::IOBuffer(kBufferSize)) {
}
- virtual void OnReceivedRedirect(URLRequest* request, const GURL& new_url,
+ virtual void OnReceivedRedirect(net::URLRequest* request, const GURL& new_url,
bool* defer_redirect) {
received_redirect_count_++;
if (quit_on_redirect_) {
@@ -224,7 +228,7 @@ class TestDelegate : public URLRequest::Delegate {
}
}
- virtual void OnResponseStarted(URLRequest* request) {
+ virtual void OnResponseStarted(net::URLRequest* request) {
// It doesn't make sense for the request to have IO pending at this point.
DCHECK(!request->status().is_io_pending());
@@ -247,7 +251,7 @@ class TestDelegate : public URLRequest::Delegate {
}
}
- virtual void OnReadCompleted(URLRequest* request, int bytes_read) {
+ virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) {
// It doesn't make sense for the request to have IO pending at this point.
DCHECK(!request->status().is_io_pending());
@@ -283,12 +287,13 @@ class TestDelegate : public URLRequest::Delegate {
request->Cancel();
}
- virtual void OnResponseCompleted(URLRequest* request) {
+ virtual void OnResponseCompleted(net::URLRequest* request) {
if (quit_on_complete_)
MessageLoop::current()->Quit();
}
- void OnAuthRequired(URLRequest* request, net::AuthChallengeInfo* auth_info) {
+ void OnAuthRequired(net::URLRequest* request,
+ net::AuthChallengeInfo* auth_info) {
if (!username_.empty() || !password_.empty()) {
request->SetAuth(username_, password_);
} else {
@@ -296,7 +301,7 @@ class TestDelegate : public URLRequest::Delegate {
}
}
- virtual void OnSSLCertificateError(URLRequest* request,
+ virtual void OnSSLCertificateError(net::URLRequest* request,
int cert_error,
net::X509Certificate* cert) {
// The caller can control whether it needs all SSL requests to go through,
@@ -309,7 +314,7 @@ class TestDelegate : public URLRequest::Delegate {
request->Cancel();
}
- virtual void OnGetCookies(URLRequest* request, bool blocked_by_policy) {
+ virtual void OnGetCookies(net::URLRequest* request, bool blocked_by_policy) {
if (blocked_by_policy) {
blocked_get_cookies_count_++;
if (cancel_in_getcookiesblocked_)
@@ -317,7 +322,7 @@ class TestDelegate : public URLRequest::Delegate {
}
}
- virtual void OnSetCookie(URLRequest* request,
+ virtual void OnSetCookie(net::URLRequest* request,
const std::string& cookie_line,
const net::CookieOptions& options,
bool blocked_by_policy) {
diff --git a/net/websockets/websocket_job.cc b/net/websockets/websocket_job.cc
index a1e2dde..44c944d 100644
--- a/net/websockets/websocket_job.cc
+++ b/net/websockets/websocket_job.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/lazy_instance.h"
#include "base/string_tokenizer.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_errors.h"
@@ -39,20 +40,23 @@ net::SocketStreamJob* WebSocketJobFactory(
class WebSocketJobInitSingleton {
private:
- friend struct DefaultSingletonTraits<WebSocketJobInitSingleton>;
+ friend struct base::DefaultLazyInstanceTraits<WebSocketJobInitSingleton>;
WebSocketJobInitSingleton() {
net::SocketStreamJob::RegisterProtocolFactory("ws", WebSocketJobFactory);
net::SocketStreamJob::RegisterProtocolFactory("wss", WebSocketJobFactory);
}
};
+static base::LazyInstance<WebSocketJobInitSingleton> g_websocket_job_init(
+ base::LINKER_INITIALIZED);
+
} // anonymous namespace
namespace net {
// static
void WebSocketJob::EnsureInit() {
- Singleton<WebSocketJobInitSingleton>::get();
+ g_websocket_job_init.Get();
}
WebSocketJob::WebSocketJob(SocketStream::Delegate* delegate)
@@ -144,8 +148,8 @@ void WebSocketJob::RestartWithAuth(
void WebSocketJob::DetachDelegate() {
state_ = CLOSED;
- Singleton<WebSocketThrottle>::get()->RemoveFromQueue(this);
- Singleton<WebSocketThrottle>::get()->WakeupSocketIfNecessary();
+ WebSocketThrottle::GetInstance()->RemoveFromQueue(this);
+ WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary();
scoped_refptr<WebSocketJob> protect(this);
@@ -165,7 +169,7 @@ int WebSocketJob::OnStartOpenConnection(
DCHECK(!callback_);
state_ = CONNECTING;
addresses_.Copy(socket->address_list().head(), true);
- Singleton<WebSocketThrottle>::get()->PutInQueue(this);
+ WebSocketThrottle::GetInstance()->PutInQueue(this);
if (!waiting_)
return OK;
callback_ = callback;
@@ -237,8 +241,8 @@ void WebSocketJob::OnReceivedData(
void WebSocketJob::OnClose(SocketStream* socket) {
state_ = CLOSED;
- Singleton<WebSocketThrottle>::get()->RemoveFromQueue(this);
- Singleton<WebSocketThrottle>::get()->WakeupSocketIfNecessary();
+ WebSocketThrottle::GetInstance()->RemoveFromQueue(this);
+ WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary();
scoped_refptr<WebSocketJob> protect(this);
@@ -405,8 +409,8 @@ void WebSocketJob::SaveNextCookie() {
handshake_response_.reset();
- Singleton<WebSocketThrottle>::get()->RemoveFromQueue(this);
- Singleton<WebSocketThrottle>::get()->WakeupSocketIfNecessary();
+ WebSocketThrottle::GetInstance()->RemoveFromQueue(this);
+ WebSocketThrottle::GetInstance()->WakeupSocketIfNecessary();
return;
}
diff --git a/net/websockets/websocket_job_unittest.cc b/net/websockets/websocket_job_unittest.cc
index 53d4a62..43d8509 100644
--- a/net/websockets/websocket_job_unittest.cc
+++ b/net/websockets/websocket_job_unittest.cc
@@ -222,7 +222,7 @@ class WebSocketJobTest : public PlatformTest {
addr.ai_addr = reinterpret_cast<sockaddr*>(&sa_in);
addr.ai_next = NULL;
websocket_->addresses_.Copy(&addr, true);
- Singleton<WebSocketThrottle>::get()->PutInQueue(websocket_);
+ WebSocketThrottle::GetInstance()->PutInQueue(websocket_);
}
WebSocketJob::State GetWebSocketJobState() {
return websocket_->state_;
@@ -230,7 +230,7 @@ class WebSocketJobTest : public PlatformTest {
void CloseWebSocketJob() {
if (websocket_->socket_) {
websocket_->socket_->DetachDelegate();
- Singleton<WebSocketThrottle>::get()->RemoveFromQueue(websocket_);
+ WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_);
}
websocket_->state_ = WebSocketJob::CLOSED;
websocket_->delegate_ = NULL;
diff --git a/net/websockets/websocket_net_log_params.cc b/net/websockets/websocket_net_log_params.cc
new file mode 100644
index 0000000..53b46c8
--- /dev/null
+++ b/net/websockets/websocket_net_log_params.cc
@@ -0,0 +1,51 @@
+// 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/websockets/websocket_net_log_params.h"
+
+namespace net {
+
+NetLogWebSocketHandshakeParameter::NetLogWebSocketHandshakeParameter(
+ const std::string& headers)
+ : headers_(headers) {
+}
+
+Value* NetLogWebSocketHandshakeParameter::ToValue() const {
+ DictionaryValue* dict = new DictionaryValue();
+ ListValue* headers = new ListValue();
+
+ size_t last = 0;
+ size_t headers_size = headers_.size();
+ size_t pos = 0;
+ while (pos <= headers_size) {
+ if (pos == headers_size ||
+ (headers_[pos] == '\r' &&
+ pos + 1 < headers_size && headers_[pos + 1] == '\n')) {
+ std::string entry = headers_.substr(last, pos - last);
+ pos += 2;
+ last = pos;
+
+ headers->Append(new StringValue(entry));
+
+ if (entry.empty()) {
+ // Dump WebSocket key3.
+ std::string key;
+ for (; pos < headers_size; ++pos) {
+ key += base::StringPrintf("\\x%02x", headers_[pos] & 0xff);
+ }
+ headers->Append(new StringValue(key));
+ break;
+ }
+ } else {
+ ++pos;
+ }
+ }
+
+ dict->Set("headers", headers);
+ return dict;
+}
+
+NetLogWebSocketHandshakeParameter::~NetLogWebSocketHandshakeParameter() {}
+
+} // namespace net
diff --git a/net/websockets/websocket_net_log_params.h b/net/websockets/websocket_net_log_params.h
index 4cd058f..1da234c 100644
--- a/net/websockets/websocket_net_log_params.h
+++ b/net/websockets/websocket_net_log_params.h
@@ -21,47 +21,12 @@ namespace net {
class NetLogWebSocketHandshakeParameter : public NetLog::EventParameters {
public:
- explicit NetLogWebSocketHandshakeParameter(const std::string& headers)
- : headers_(headers) {
- }
+ explicit NetLogWebSocketHandshakeParameter(const std::string& headers);
- Value* ToValue() const {
- DictionaryValue* dict = new DictionaryValue();
- ListValue* headers = new ListValue();
-
- size_t last = 0;
- size_t headers_size = headers_.size();
- size_t pos = 0;
- while (pos <= headers_size) {
- if (pos == headers_size ||
- (headers_[pos] == '\r' &&
- pos + 1 < headers_size && headers_[pos + 1] == '\n')) {
- std::string entry = headers_.substr(last, pos - last);
- pos += 2;
- last = pos;
-
- headers->Append(new StringValue(entry));
-
- if (entry.empty()) {
- // Dump WebSocket key3.
- std::string key;
- for (; pos < headers_size; ++pos) {
- key += base::StringPrintf("\\x%02x", headers_[pos] & 0xff);
- }
- headers->Append(new StringValue(key));
- break;
- }
- } else {
- ++pos;
- }
- }
-
- dict->Set("headers", headers);
- return dict;
- }
+ virtual Value* ToValue() const;
private:
- ~NetLogWebSocketHandshakeParameter() {}
+ virtual ~NetLogWebSocketHandshakeParameter();
const std::string headers_;
diff --git a/net/websockets/websocket_throttle.cc b/net/websockets/websocket_throttle.cc
index 2d62815..c714de6 100644
--- a/net/websockets/websocket_throttle.cc
+++ b/net/websockets/websocket_throttle.cc
@@ -54,6 +54,11 @@ WebSocketThrottle::~WebSocketThrottle() {
DCHECK(addr_map_.empty());
}
+// static
+WebSocketThrottle* WebSocketThrottle::GetInstance() {
+ return Singleton<WebSocketThrottle>::get();
+}
+
void WebSocketThrottle::PutInQueue(WebSocketJob* job) {
queue_.push_back(job);
const AddressList& address_list = job->address_list();
diff --git a/net/websockets/websocket_throttle.h b/net/websockets/websocket_throttle.h
index 0849834..9becc62 100644
--- a/net/websockets/websocket_throttle.h
+++ b/net/websockets/websocket_throttle.h
@@ -10,7 +10,8 @@
#include <string>
#include "base/hash_tables.h"
-#include "base/singleton.h"
+
+template <typename T> struct DefaultSingletonTraits;
namespace net {
@@ -27,6 +28,9 @@ class WebSocketJob;
// for that connection to have failed.
class WebSocketThrottle {
public:
+ // Returns the singleton instance.
+ static WebSocketThrottle* GetInstance();
+
// Puts |job| in |queue_| and queues for the destination addresses
// of |job|.
// If other job is using the same destination address, set |job| waiting.