• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
DefaultClientSocketFactory()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 
~DefaultClientSocketFactory()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 
OnCertAdded(const X509Certificate * cert)59   virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE {
60     ClearSSLSessionCache();
61   }
62 
OnCACertChanged(const X509Certificate * cert)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 
CreateDatagramClientSocket(DatagramSocket::BindType bind_type,const RandIntCallback & rand_int_cb,NetLog * net_log,const NetLog::Source & source)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 
CreateTransportClientSocket(const AddressList & addresses,NetLog * net_log,const NetLog::Source & source)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 
CreateSSLClientSocket(scoped_ptr<ClientSocketHandle> transport_socket,const HostPortPair & host_and_port,const SSLConfig & ssl_config,const SSLClientSocketContext & context)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 
ClearSSLSessionCache()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
GetDefaultFactory()138 ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() {
139   return g_default_client_socket_factory.Pointer();
140 }
141 
142 }  // namespace net
143