summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-10 04:16:25 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-10 04:16:25 +0000
commit62635c758fce2b22a1cf5acdc57579bb5801b2e3 (patch)
tree4085d65bbf01078b722cbcef5930e157d7f793be /net
parentd7f6e73fb05992d784e55df2a1ed25924b5d79f3 (diff)
downloadchromium_src-62635c758fce2b22a1cf5acdc57579bb5801b2e3.zip
chromium_src-62635c758fce2b22a1cf5acdc57579bb5801b2e3.tar.gz
chromium_src-62635c758fce2b22a1cf5acdc57579bb5801b2e3.tar.bz2
Define a new CertDatabase::Observer abstract class which can be implemented by classes which wish to be notified when a new ssl client cert is added.
Register SpdySessionPool, SocketPoolManager and SSLClientAuthCache as observers. Notify observers in CertDatabase::AddUserCert(); BUG=75326 Review URL: http://codereview.chromium.org/6588014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77599 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/cert_database.cc35
-rw-r--r--net/base/cert_database.h31
-rw-r--r--net/base/cert_database_mac.cc2
-rw-r--r--net/base/cert_database_nss.cc1
-rw-r--r--net/base/cert_database_win.cc1
-rw-r--r--net/base/ssl_client_auth_cache.cc10
-rw-r--r--net/base/ssl_client_auth_cache.h7
-rw-r--r--net/base/ssl_client_auth_cache_unittest.cc6
-rw-r--r--net/socket/client_socket_factory.cc18
-rw-r--r--net/socket/client_socket_pool_manager.cc17
-rw-r--r--net/socket/client_socket_pool_manager.h7
-rw-r--r--net/spdy/spdy_session_pool.cc6
-rw-r--r--net/spdy/spdy_session_pool.h7
13 files changed, 133 insertions, 15 deletions
diff --git a/net/base/cert_database.cc b/net/base/cert_database.cc
index 313a6dd0..f049aca 100644
--- a/net/base/cert_database.cc
+++ b/net/base/cert_database.cc
@@ -4,6 +4,8 @@
#include "net/base/cert_database.h"
+#include "base/observer_list_threadsafe.h"
+#include "base/singleton.h"
#include "net/base/x509_certificate.h"
namespace net {
@@ -16,4 +18,37 @@ CertDatabase::ImportCertFailure::ImportCertFailure(
CertDatabase::ImportCertFailure::~ImportCertFailure() {
}
+// CertDatabaseNotifier notifies registered observers when new user certificates
+// are added to the database.
+class CertDatabaseNotifier {
+ public:
+ CertDatabaseNotifier()
+ : observer_list_(new ObserverListThreadSafe<CertDatabase::Observer>) {
+ }
+
+ static CertDatabaseNotifier* GetInstance() {
+ return Singleton<CertDatabaseNotifier>::get();
+ }
+
+ friend struct DefaultSingletonTraits<CertDatabaseNotifier>;
+ friend class CertDatabase;
+
+ private:
+ const scoped_refptr<ObserverListThreadSafe<CertDatabase::Observer> >
+ observer_list_;
+};
+
+void CertDatabase::AddObserver(Observer* observer) {
+ CertDatabaseNotifier::GetInstance()->observer_list_->AddObserver(observer);
+}
+
+void CertDatabase::RemoveObserver(Observer* observer) {
+ CertDatabaseNotifier::GetInstance()->observer_list_->RemoveObserver(observer);
+}
+
+void CertDatabase::NotifyObserversOfUserCertAdded(X509Certificate* cert) {
+ CertDatabaseNotifier::GetInstance()->observer_list_->Notify(
+ &CertDatabase::Observer::OnUserCertAdded, make_scoped_refptr(cert));
+}
+
} // namespace net
diff --git a/net/base/cert_database.h b/net/base/cert_database.h
index 0e7bdbd..5760dff 100644
--- a/net/base/cert_database.h
+++ b/net/base/cert_database.h
@@ -31,6 +31,25 @@ typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
class CertDatabase {
public:
+
+ // A CertDatabase::Observer will be notified every time a new user
+ // certificate is added to the database. Observers can register themselves
+ // via CertDatabase::AddObserver, and can un-register with
+ // CertDatabase::RemoveObserver.
+ class Observer {
+ public:
+ virtual ~Observer() {}
+
+ // Will be called when a new user certificate is added.
+ virtual void OnUserCertAdded(X509Certificate* cert) = 0;
+
+ protected:
+ Observer() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Observer);
+ };
+
// Stores per-certificate error codes for import failures.
struct ImportCertFailure {
public:
@@ -141,7 +160,19 @@ class CertDatabase {
bool IsReadOnly(const X509Certificate* cert) const;
#endif
+ // Registers |observer| to receive notifications of certificate changes. The
+ // thread on which this is called is the thread on which |observer| will be
+ // called back with notifications.
+ static void AddObserver(Observer* observer);
+
+ // Unregisters |observer| from receiving notifications. This must be called
+ // on the same thread on which AddObserver() was called.
+ static void RemoveObserver(Observer* observer);
+
private:
+ // Broadcasts a notification to all registered observers.
+ static void NotifyObserversOfUserCertAdded(X509Certificate* cert);
+
DISALLOW_COPY_AND_ASSIGN(CertDatabase);
};
diff --git a/net/base/cert_database_mac.cc b/net/base/cert_database_mac.cc
index e90a712..66828ad 100644
--- a/net/base/cert_database_mac.cc
+++ b/net/base/cert_database_mac.cc
@@ -48,6 +48,8 @@ int CertDatabase::AddUserCert(X509Certificate* cert) {
}
switch (err) {
case noErr:
+ CertDatabase::NotifyObserversOfUserCertAdded(cert);
+ // Fall through.
case errSecDuplicateItem:
return OK;
default:
diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc
index 7e1abaa9..60cc4bc 100644
--- a/net/base/cert_database_nss.cc
+++ b/net/base/cert_database_nss.cc
@@ -89,6 +89,7 @@ int CertDatabase::AddUserCert(X509Certificate* cert_obj) {
return ERR_ADD_USER_CERT_FAILED;
}
PK11_FreeSlot(slot);
+ CertDatabase::NotifyObserversOfUserCertAdded(cert_obj);
return OK;
}
diff --git a/net/base/cert_database_win.cc b/net/base/cert_database_win.cc
index 4c5e8df..038fc1c 100644
--- a/net/base/cert_database_win.cc
+++ b/net/base/cert_database_win.cc
@@ -50,6 +50,7 @@ int CertDatabase::AddUserCert(X509Certificate* cert) {
if (!added)
return ERR_ADD_USER_CERT_FAILED;
+ CertDatabase::NotifyObserversOfUserCertAdded(cert);
return OK;
}
diff --git a/net/base/ssl_client_auth_cache.cc b/net/base/ssl_client_auth_cache.cc
index cdaad7f..ecfada8 100644
--- a/net/base/ssl_client_auth_cache.cc
+++ b/net/base/ssl_client_auth_cache.cc
@@ -9,9 +9,13 @@
namespace net {
-SSLClientAuthCache::SSLClientAuthCache() {}
+SSLClientAuthCache::SSLClientAuthCache() {
+ CertDatabase::AddObserver(this);
+}
-SSLClientAuthCache::~SSLClientAuthCache() {}
+SSLClientAuthCache::~SSLClientAuthCache() {
+ CertDatabase::RemoveObserver(this);
+}
bool SSLClientAuthCache::Lookup(
const std::string& server,
@@ -37,7 +41,7 @@ void SSLClientAuthCache::Remove(const std::string& server) {
cache_.erase(server);
}
-void SSLClientAuthCache::Clear() {
+void SSLClientAuthCache::OnUserCertAdded(X509Certificate* cert) {
cache_.clear();
}
diff --git a/net/base/ssl_client_auth_cache.h b/net/base/ssl_client_auth_cache.h
index b37164a..6cc1d12 100644
--- a/net/base/ssl_client_auth_cache.h
+++ b/net/base/ssl_client_auth_cache.h
@@ -10,6 +10,7 @@
#include <map>
#include "base/ref_counted.h"
+#include "net/base/cert_database.h"
namespace net {
@@ -22,7 +23,7 @@ class X509Certificate;
//
// TODO(wtc): This class is based on FtpAuthCache. We can extract the common
// code to a template class.
-class SSLClientAuthCache {
+class SSLClientAuthCache : public CertDatabase::Observer {
public:
SSLClientAuthCache();
~SSLClientAuthCache();
@@ -44,8 +45,8 @@ class SSLClientAuthCache {
// Remove the client certificate for |server| from the cache, if one exists.
void Remove(const std::string& server);
- // Removes all cache entries.
- void Clear();
+ // CertDatabase::Observer methods:
+ virtual void OnUserCertAdded(X509Certificate* cert);
private:
typedef std::string AuthCacheKey;
diff --git a/net/base/ssl_client_auth_cache_unittest.cc b/net/base/ssl_client_auth_cache_unittest.cc
index 144e114..6408887 100644
--- a/net/base/ssl_client_auth_cache_unittest.cc
+++ b/net/base/ssl_client_auth_cache_unittest.cc
@@ -137,8 +137,8 @@ TEST(SSLClientAuthCacheTest, LookupNullPreference) {
EXPECT_EQ(NULL, cached_cert.get());
}
-// Check that the Clear() method removes all cache entries.
-TEST(SSLClientAuthCacheTest, Clear) {
+// Check that the OnUserCertAdded() method removes all cache entries.
+TEST(SSLClientAuthCacheTest, OnUserCertAdded) {
SSLClientAuthCache cache;
base::Time start_date = base::Time::Now();
base::Time expiration_date = start_date + base::TimeDelta::FromDays(1);
@@ -161,7 +161,7 @@ TEST(SSLClientAuthCacheTest, Clear) {
EXPECT_TRUE(cache.Lookup(server2, &cached_cert));
EXPECT_EQ(NULL, cached_cert.get());
- cache.Clear();
+ cache.OnUserCertAdded(NULL);
// Check that we no longer have entries for either server.
EXPECT_FALSE(cache.Lookup(server1, &cached_cert));
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 2eb90e5..e8e6f2f 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -6,6 +6,7 @@
#include "base/lazy_instance.h"
#include "build/build_config.h"
+#include "net/base/cert_database.h"
#include "net/socket/client_socket_handle.h"
#if defined(OS_WIN)
#include "net/socket/ssl_client_socket_nss.h"
@@ -23,12 +24,27 @@
namespace net {
+class X509Certificate;
+
namespace {
bool g_use_system_ssl = false;
-class DefaultClientSocketFactory : public ClientSocketFactory {
+class DefaultClientSocketFactory : public ClientSocketFactory,
+ public CertDatabase::Observer {
public:
+ DefaultClientSocketFactory() {
+ CertDatabase::AddObserver(this);
+ }
+
+ virtual ~DefaultClientSocketFactory() {
+ CertDatabase::RemoveObserver(this);
+ }
+
+ virtual void OnUserCertAdded(X509Certificate* cert) {
+ ClearSSLSessionCache();
+ }
+
virtual ClientSocket* CreateTCPClientSocket(
const AddressList& addresses,
NetLog* net_log,
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index 999b4e6..3d12256 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -8,12 +8,15 @@
#include "net/socket/client_socket_pool_manager.h"
+#include <string>
+
#include "base/logging.h"
#include "base/values.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_proxy_client_socket_pool.h"
-#include "net/socket/client_socket_pool_histograms.h"
#include "net/proxy/proxy_service.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket_pool.h"
#include "net/socket/tcp_client_socket_pool.h"
@@ -98,9 +101,13 @@ ClientSocketPoolManager::ClientSocketPoolManager(
tcp_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"),
ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"),
http_proxy_pool_histograms_("HTTPProxy"),
- ssl_socket_pool_for_proxies_histograms_("SSLForProxies") {}
+ ssl_socket_pool_for_proxies_histograms_("SSLForProxies") {
+ CertDatabase::AddObserver(this);
+}
-ClientSocketPoolManager::~ClientSocketPoolManager() {}
+ClientSocketPoolManager::~ClientSocketPoolManager() {
+ CertDatabase::RemoveObserver(this);
+}
void ClientSocketPoolManager::FlushSocketPools() {
// Flush the highest level pools first, since higher level pools may release
@@ -392,4 +399,8 @@ Value* ClientSocketPoolManager::SocketPoolInfoToValue() const {
return list;
}
+void ClientSocketPoolManager::OnUserCertAdded(X509Certificate* cert) {
+ FlushSocketPools();
+}
+
} // namespace net
diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h
index 7d610a9..45a0c23 100644
--- a/net/socket/client_socket_pool_manager.h
+++ b/net/socket/client_socket_pool_manager.h
@@ -17,6 +17,7 @@
#include "base/stl_util-inl.h"
#include "base/template_util.h"
#include "base/threading/non_thread_safe.h"
+#include "net/base/cert_database.h"
#include "net/socket/client_socket_pool_histograms.h"
class Value;
@@ -57,7 +58,8 @@ class OwnedPoolMap : public std::map<Key, Value> {
} // namespace internal
-class ClientSocketPoolManager : public base::NonThreadSafe {
+class ClientSocketPoolManager : public base::NonThreadSafe,
+ public CertDatabase::Observer {
public:
ClientSocketPoolManager(NetLog* net_log,
ClientSocketFactory* socket_factory,
@@ -94,6 +96,9 @@ class ClientSocketPoolManager : public base::NonThreadSafe {
// responsible for deleting the returned value.
Value* SocketPoolInfoToValue() const;
+ // CertDatabase::Observer methods:
+ virtual void OnUserCertAdded(X509Certificate* cert);
+
private:
friend class HttpNetworkSessionPeer;
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index e2cae2b..0220d11 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -22,6 +22,7 @@ SpdySessionPool::SpdySessionPool(SSLConfigService* ssl_config_service)
NetworkChangeNotifier::AddIPAddressObserver(this);
if (ssl_config_service_)
ssl_config_service_->AddObserver(this);
+ CertDatabase::AddObserver(this);
}
SpdySessionPool::~SpdySessionPool() {
@@ -30,6 +31,7 @@ SpdySessionPool::~SpdySessionPool() {
if (ssl_config_service_)
ssl_config_service_->RemoveObserver(this);
NetworkChangeNotifier::RemoveIPAddressObserver(this);
+ CertDatabase::RemoveObserver(this);
}
scoped_refptr<SpdySession> SpdySessionPool::Get(
@@ -136,6 +138,10 @@ void SpdySessionPool::OnSSLConfigChanged() {
CloseCurrentSessions();
}
+void SpdySessionPool::OnUserCertAdded(X509Certificate* cert) {
+ CloseCurrentSessions();
+}
+
const HostPortProxyPair& SpdySessionPool::NormalizeListPair(
const HostPortProxyPair& host_port_proxy_pair) const {
if (!g_force_single_domain)
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index 16125e0..caaaa67 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -14,6 +14,7 @@
#include "base/gtest_prod_util.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
+#include "net/base/cert_database.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
@@ -33,7 +34,8 @@ class SpdySession;
// TODO(mbelshe): Make this production ready.
class SpdySessionPool
: public NetworkChangeNotifier::IPAddressObserver,
- public SSLConfigService::Observer {
+ public SSLConfigService::Observer,
+ public CertDatabase::Observer {
public:
explicit SpdySessionPool(SSLConfigService* ssl_config_service);
virtual ~SpdySessionPool();
@@ -105,6 +107,9 @@ class SpdySessionPool
// A debugging mode where we compress all accesses through a single domain.
static void ForceSingleDomain() { g_force_single_domain = true; }
+ // CertDatabase::Observer methods:
+ virtual void OnUserCertAdded(X509Certificate* cert);
+
private:
friend class SpdySessionPoolPeer; // For testing.
friend class SpdyNetworkTransactionTest; // For testing.