1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/socket/client_socket_factory.h" 6 7 #include "base/lazy_instance.h" 8 #include "base/thread_task_runner_handle.h" 9 #include "base/threading/sequenced_worker_pool.h" 10 #include "build/build_config.h" 11 #include "net/cert/cert_database.h" 12 #include "net/socket/client_socket_handle.h" 13 #if defined(USE_OPENSSL) 14 #include "net/socket/ssl_client_socket_openssl.h" 15 #elif defined(USE_NSS) || defined(OS_MACOSX) || defined(OS_WIN) 16 #include "net/socket/ssl_client_socket_nss.h" 17 #endif 18 #include "net/socket/tcp_client_socket.h" 19 #include "net/udp/udp_client_socket.h" 20 21 namespace net { 22 23 class X509Certificate; 24 25 namespace { 26 27 // ChromeOS and Linux may require interaction with smart cards or TPMs, which 28 // may cause NSS functions to block for upwards of several seconds. To avoid 29 // blocking all activity on the current task runner, such as network or IPC 30 // traffic, run NSS SSL functions on a dedicated thread. 31 #if defined(OS_CHROMEOS) || defined(OS_LINUX) 32 bool g_use_dedicated_nss_thread = true; 33 #else 34 bool g_use_dedicated_nss_thread = false; 35 #endif 36 37 class DefaultClientSocketFactory : public ClientSocketFactory, 38 public CertDatabase::Observer { 39 public: 40 DefaultClientSocketFactory() { 41 if (g_use_dedicated_nss_thread) { 42 // Use a single thread for the worker pool. 43 worker_pool_ = new base::SequencedWorkerPool(1, "NSS SSL Thread"); 44 nss_thread_task_runner_ = 45 worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior( 46 worker_pool_->GetSequenceToken(), 47 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 48 } 49 50 CertDatabase::GetInstance()->AddObserver(this); 51 } 52 53 virtual ~DefaultClientSocketFactory() { 54 // Note: This code never runs, as the factory is defined as a Leaky 55 // singleton. 56 CertDatabase::GetInstance()->RemoveObserver(this); 57 } 58 59 virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE { 60 ClearSSLSessionCache(); 61 } 62 63 virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE { 64 // Per wtc, we actually only need to flush when trust is reduced. 65 // Always flush now because OnCACertChanged does not tell us this. 66 // See comments in ClientSocketPoolManager::OnCACertChanged. 67 ClearSSLSessionCache(); 68 } 69 70 virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket( 71 DatagramSocket::BindType bind_type, 72 const RandIntCallback& rand_int_cb, 73 NetLog* net_log, 74 const NetLog::Source& source) OVERRIDE { 75 return scoped_ptr<DatagramClientSocket>( 76 new UDPClientSocket(bind_type, rand_int_cb, net_log, source)); 77 } 78 79 virtual scoped_ptr<StreamSocket> CreateTransportClientSocket( 80 const AddressList& addresses, 81 NetLog* net_log, 82 const NetLog::Source& source) OVERRIDE { 83 return scoped_ptr<StreamSocket>( 84 new TCPClientSocket(addresses, net_log, source)); 85 } 86 87 virtual scoped_ptr<SSLClientSocket> CreateSSLClientSocket( 88 scoped_ptr<ClientSocketHandle> transport_socket, 89 const HostPortPair& host_and_port, 90 const SSLConfig& ssl_config, 91 const SSLClientSocketContext& context) OVERRIDE { 92 // nss_thread_task_runner_ may be NULL if g_use_dedicated_nss_thread is 93 // false or if the dedicated NSS thread failed to start. If so, cause NSS 94 // functions to execute on the current task runner. 95 // 96 // Note: The current task runner is obtained on each call due to unit 97 // tests, which may create and tear down the current thread's TaskRunner 98 // between each test. Because the DefaultClientSocketFactory is leaky, it 99 // may span multiple tests, and thus the current task runner may change 100 // from call to call. 101 scoped_refptr<base::SequencedTaskRunner> nss_task_runner( 102 nss_thread_task_runner_); 103 if (!nss_task_runner.get()) 104 nss_task_runner = base::ThreadTaskRunnerHandle::Get(); 105 106 #if defined(USE_OPENSSL) 107 return scoped_ptr<SSLClientSocket>( 108 new SSLClientSocketOpenSSL(transport_socket.Pass(), host_and_port, 109 ssl_config, context)); 110 #elif defined(USE_NSS) || defined(OS_MACOSX) || defined(OS_WIN) 111 return scoped_ptr<SSLClientSocket>( 112 new SSLClientSocketNSS(nss_task_runner.get(), 113 transport_socket.Pass(), 114 host_and_port, 115 ssl_config, 116 context)); 117 #else 118 NOTIMPLEMENTED(); 119 return scoped_ptr<SSLClientSocket>(); 120 #endif 121 } 122 123 virtual void ClearSSLSessionCache() OVERRIDE { 124 SSLClientSocket::ClearSessionCache(); 125 } 126 127 private: 128 scoped_refptr<base::SequencedWorkerPool> worker_pool_; 129 scoped_refptr<base::SequencedTaskRunner> nss_thread_task_runner_; 130 }; 131 132 static base::LazyInstance<DefaultClientSocketFactory>::Leaky 133 g_default_client_socket_factory = LAZY_INSTANCE_INITIALIZER; 134 135 } // namespace 136 137 // static 138 ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() { 139 return g_default_client_socket_factory.Pointer(); 140 } 141 142 } // namespace net 143