Home | History | Annotate | Download | only in socket
      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 OnCertTrustChanged(const X509Certificate* cert) OVERRIDE {
     64     // Per wtc, we actually only need to flush when trust is reduced.
     65     // Always flush now because OnCertTrustChanged does not tell us this.
     66     // See comments in ClientSocketPoolManager::OnCertTrustChanged.
     67     ClearSSLSessionCache();
     68   }
     69 
     70   virtual 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 new UDPClientSocket(bind_type, rand_int_cb, net_log, source);
     76   }
     77 
     78   virtual StreamSocket* CreateTransportClientSocket(
     79       const AddressList& addresses,
     80       NetLog* net_log,
     81       const NetLog::Source& source) OVERRIDE {
     82     return new TCPClientSocket(addresses, net_log, source);
     83   }
     84 
     85   virtual SSLClientSocket* CreateSSLClientSocket(
     86       ClientSocketHandle* transport_socket,
     87       const HostPortPair& host_and_port,
     88       const SSLConfig& ssl_config,
     89       const SSLClientSocketContext& context) OVERRIDE {
     90     // nss_thread_task_runner_ may be NULL if g_use_dedicated_nss_thread is
     91     // false or if the dedicated NSS thread failed to start. If so, cause NSS
     92     // functions to execute on the current task runner.
     93     //
     94     // Note: The current task runner is obtained on each call due to unit
     95     // tests, which may create and tear down the current thread's TaskRunner
     96     // between each test. Because the DefaultClientSocketFactory is leaky, it
     97     // may span multiple tests, and thus the current task runner may change
     98     // from call to call.
     99     scoped_refptr<base::SequencedTaskRunner> nss_task_runner(
    100         nss_thread_task_runner_);
    101     if (!nss_task_runner.get())
    102       nss_task_runner = base::ThreadTaskRunnerHandle::Get();
    103 
    104 #if defined(USE_OPENSSL)
    105     return new SSLClientSocketOpenSSL(transport_socket, host_and_port,
    106                                       ssl_config, context);
    107 #elif defined(USE_NSS) || defined(OS_MACOSX) || defined(OS_WIN)
    108     return new SSLClientSocketNSS(nss_task_runner.get(),
    109                                   transport_socket,
    110                                   host_and_port,
    111                                   ssl_config,
    112                                   context);
    113 #else
    114     NOTIMPLEMENTED();
    115     return NULL;
    116 #endif
    117   }
    118 
    119   virtual void ClearSSLSessionCache() OVERRIDE {
    120     SSLClientSocket::ClearSessionCache();
    121   }
    122 
    123  private:
    124   scoped_refptr<base::SequencedWorkerPool> worker_pool_;
    125   scoped_refptr<base::SequencedTaskRunner> nss_thread_task_runner_;
    126 };
    127 
    128 static base::LazyInstance<DefaultClientSocketFactory>::Leaky
    129     g_default_client_socket_factory = LAZY_INSTANCE_INITIALIZER;
    130 
    131 }  // namespace
    132 
    133 // Deprecated function (http://crbug.com/37810) that takes a StreamSocket.
    134 SSLClientSocket* ClientSocketFactory::CreateSSLClientSocket(
    135     StreamSocket* transport_socket,
    136     const HostPortPair& host_and_port,
    137     const SSLConfig& ssl_config,
    138     const SSLClientSocketContext& context) {
    139   ClientSocketHandle* socket_handle = new ClientSocketHandle();
    140   socket_handle->set_socket(transport_socket);
    141   return CreateSSLClientSocket(socket_handle, host_and_port, ssl_config,
    142                                context);
    143 }
    144 
    145 // static
    146 ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() {
    147   return g_default_client_socket_factory.Pointer();
    148 }
    149 
    150 }  // namespace net
    151