Index: net/socket/client_socket_factory.cc |
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc |
index 42f6d4f20cebcf90c4d82d2c1be78d6d38ed099c..4c2ce3215aaff4e62e32e308b33ddc8f962de634 100644 |
--- a/net/socket/client_socket_factory.cc |
+++ b/net/socket/client_socket_factory.cc |
@@ -5,6 +5,8 @@ |
#include "net/socket/client_socket_factory.h" |
#include "base/lazy_instance.h" |
+#include "base/thread_task_runner_handle.h" |
+#include "base/threading/thread.h" |
#include "build/build_config.h" |
#include "net/base/cert_database.h" |
#include "net/socket/client_socket_handle.h" |
@@ -31,14 +33,32 @@ namespace { |
bool g_use_system_ssl = false; |
+// ChromeOS uses a hardware TPM module that may cause NSS operations to |
+// block for upwards of several seconds. To avoid blocking all network and |
+// IPC activity, run NSS SSL functions on a dedicated thread. |
+#if defined(OS_CHROMEOS) |
+bool g_use_dedicated_nss_thread = true; |
+#else |
+bool g_use_dedicated_nss_thread = false; |
+#endif |
+ |
class DefaultClientSocketFactory : public ClientSocketFactory, |
public CertDatabase::Observer { |
public: |
- DefaultClientSocketFactory() { |
+ DefaultClientSocketFactory() |
+ : nss_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
+ if (g_use_dedicated_nss_thread) { |
+ nss_thread_.reset(new base::Thread("NSS SSL Thread")); |
+ if (nss_thread_->Start()) |
+ nss_task_runner_ = nss_thread_->message_loop_proxy(); |
+ } |
+ |
CertDatabase::AddObserver(this); |
} |
virtual ~DefaultClientSocketFactory() { |
+ // Note: This code never runs, as the factory is defined as a Leaky |
+ // singleton. |
CertDatabase::RemoveObserver(this); |
} |
@@ -76,26 +96,29 @@ class DefaultClientSocketFactory : public ClientSocketFactory, |
const SSLClientSocketContext& context) { |
scoped_ptr<SSLHostInfo> shi(ssl_host_info); |
-#if defined(OS_WIN) |
+#if defined(USE_OPENSSL) |
+ return new SSLClientSocketOpenSSL(transport_socket, host_and_port, |
+ ssl_config, context); |
+#elif defined(USE_NSS) |
+ return new SSLClientSocketNSS(nss_task_runner_, transport_socket, |
+ host_and_port, ssl_config, shi.release(), |
+ context); |
+#elif defined(OS_WIN) |
if (g_use_system_ssl) { |
return new SSLClientSocketWin(transport_socket, host_and_port, |
ssl_config, context); |
} |
- return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config, |
- shi.release(), context); |
-#elif defined(USE_OPENSSL) |
- return new SSLClientSocketOpenSSL(transport_socket, host_and_port, |
- ssl_config, context); |
-#elif defined(USE_NSS) |
- return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config, |
- shi.release(), context); |
+ return new SSLClientSocketNSS(nss_task_runner_, transport_socket, |
+ host_and_port, ssl_config, shi.release(), |
+ context); |
#elif defined(OS_MACOSX) |
if (g_use_system_ssl) { |
return new SSLClientSocketMac(transport_socket, host_and_port, |
ssl_config, context); |
} |
- return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config, |
- shi.release(), context); |
+ return new SSLClientSocketNSS(nss_task_runner_, transport_socket, |
+ host_and_port, ssl_config, shi.release(), |
+ context); |
#else |
NOTIMPLEMENTED(); |
return NULL; |
@@ -106,9 +129,12 @@ class DefaultClientSocketFactory : public ClientSocketFactory, |
SSLClientSocket::ClearSessionCache(); |
} |
+ private: |
+ scoped_ptr<base::Thread> nss_thread_; |
+ scoped_refptr<base::SingleThreadTaskRunner> nss_task_runner_; |
}; |
-static base::LazyInstance<DefaultClientSocketFactory> |
+static base::LazyInstance<DefaultClientSocketFactory>::Leaky |
g_default_client_socket_factory = LAZY_INSTANCE_INITIALIZER; |
} // namespace |