Index: net/cert/nss_cert_database.cc |
diff --git a/net/cert/nss_cert_database.cc b/net/cert/nss_cert_database.cc |
index 9c2a3f1ffc50e2ec278c88a2a74c90bced2b44b8..8984d5902815449448593cd8c93b5856c27b8a7c 100644 |
--- a/net/cert/nss_cert_database.cc |
+++ b/net/cert/nss_cert_database.cc |
@@ -10,9 +10,9 @@ |
#include <pk11pub.h> |
#include <secmod.h> |
+#include "base/lazy_instance.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
-#include "base/memory/singleton.h" |
#include "base/observer_list_threadsafe.h" |
#include "crypto/nss_util.h" |
#include "crypto/nss_util_internal.h" |
@@ -35,6 +35,12 @@ namespace psm = mozilla_security_manager; |
namespace net { |
+namespace { |
+base::LazyInstance<NSSCertDatabase>::Leaky |
+ g_nss_cert_database = LAZY_INSTANCE_INITIALIZER; |
+} // namespace |
+ |
+ |
NSSCertDatabase::ImportCertFailure::ImportCertFailure( |
const scoped_refptr<X509Certificate>& cert, |
int err) |
@@ -42,15 +48,55 @@ NSSCertDatabase::ImportCertFailure::ImportCertFailure( |
NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} |
+// Helper that observes events from a CertDatabaseSource and forwards them to |
+// the given CertDatabase. |
+class NSSCertDatabase::Notifier : public CertDatabaseSource::Observer { |
+ public: |
+ Notifier(NSSCertDatabase* cert_db) : cert_db_(cert_db) {} |
+ |
+ virtual ~Notifier() {} |
+ |
+ // CertDatabaseSource::Observer implementation: |
+ virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE { |
+ cert_db_->NotifyObserversOfCertAdded(cert); |
+ } |
+ |
+ virtual void OnCertRemoved(const X509Certificate* cert) OVERRIDE { |
+ cert_db_->NotifyObserversOfCertRemoved(cert); |
+ } |
+ |
+ virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE { |
+ cert_db_->NotifyObserversOfCACertChanged(cert); |
+ } |
+ |
+ private: |
+ NSSCertDatabase* cert_db_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Notifier); |
+}; |
+ |
+// static |
+NSSCertDatabase* NSSCertDatabase::GetInstanceNoWarn() { |
+ return &g_nss_cert_database.Get(); |
+ //return Singleton<NSSCertDatabase, |
+ // LeakySingletonTraits<NSSCertDatabase> >::get(); |
+} |
+ |
// static |
NSSCertDatabase* NSSCertDatabase::GetInstance() { |
- return Singleton<NSSCertDatabase, |
- LeakySingletonTraits<NSSCertDatabase> >::get(); |
+#if defined(OS_CHROMEOS) |
+ LOG(WARNING) << "Using global NSSCertDatabase. Consider using " |
+ << "NSSCertDatabaseChromeOS::GetForUser instead."; |
+#endif |
+ return NSSCertDatabase::GetInstanceNoWarn(); |
} |
NSSCertDatabase::NSSCertDatabase() |
- : observer_list_(new ObserverListThreadSafe<Observer>) { |
- crypto::EnsureNSSInit(); |
+ : observer_list_(new ObserverListThreadSafe<Observer>), |
+ notifier_(new Notifier(this)) { |
+ // This also makes sure that NSS has been initialized. |
+ CertDatabase::GetInstance()->AddSource(this); |
+ |
psm::EnsurePKCS12Init(); |
} |
@@ -71,25 +117,27 @@ void NSSCertDatabase::ListCerts(CertificateList* certs) { |
} |
CryptoModule* NSSCertDatabase::GetPublicModule() const { |
- CryptoModule* module = |
- CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot()); |
- // The module is already referenced when returned from |
- // GetPublicNSSKeySlot, so we need to deref it once. |
- PK11_FreeSlot(module->os_module_handle()); |
+ crypto::ScopedPK11Slot slot(GetPublicSlot()); |
+ CryptoModule* module = CryptoModule::CreateFromHandle(slot.get()); |
return module; |
} |
CryptoModule* NSSCertDatabase::GetPrivateModule() const { |
- CryptoModule* module = |
- CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot()); |
- // The module is already referenced when returned from |
- // GetPrivateNSSKeySlot, so we need to deref it once. |
- PK11_FreeSlot(module->os_module_handle()); |
+ crypto::ScopedPK11Slot slot(GetPrivateSlot()); |
+ CryptoModule* module = CryptoModule::CreateFromHandle(slot.get()); |
return module; |
} |
+crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const { |
+ return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()); |
+} |
+ |
+crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const { |
+ return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()); |
+} |
+ |
void NSSCertDatabase::ListModules(CryptoModuleList* modules, |
bool need_rw) const { |
modules->clear(); |
@@ -119,6 +167,9 @@ int NSSCertDatabase::ImportFromPKCS12( |
const base::string16& password, |
bool is_extractable, |
net::CertificateList* imported_certs) { |
+ DVLOG(1) << __func__ << " " |
+ << PK11_GetModuleID(module->os_module_handle()) << ":" |
+ << PK11_GetSlotID(module->os_module_handle()); |
int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), |
data.data(), data.size(), |
password, |
@@ -156,7 +207,7 @@ X509Certificate* NSSCertDatabase::FindRootInList( |
&certn_1->os_cert_handle()->subject) == SECEqual) |
return certn_1; |
- VLOG(1) << "certificate list is not a hierarchy"; |
+ DVLOG(1) << "certificate list is not a hierarchy"; |
return cert0; |
} |
@@ -164,8 +215,12 @@ bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, |
TrustBits trust_bits, |
ImportCertFailureList* not_imported) { |
X509Certificate* root = FindRootInList(certificates); |
- bool success = psm::ImportCACerts(certificates, root, trust_bits, |
- not_imported); |
+ bool success = psm::ImportCACerts( |
+ GetPublicSlot(), |
+ certificates, |
+ root, |
+ trust_bits, |
+ not_imported); |
if (success) |
NotifyObserversOfCACertChanged(NULL); |
@@ -175,7 +230,11 @@ bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, |
bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates, |
TrustBits trust_bits, |
ImportCertFailureList* not_imported) { |
- return psm::ImportServerCert(certificates, trust_bits, not_imported); |
+ return psm::ImportServerCert( |
+ GetPublicSlot(), |
+ certificates, |
+ trust_bits, |
+ not_imported); |
} |
NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust( |
@@ -331,6 +390,10 @@ void NSSCertDatabase::RemoveObserver(Observer* observer) { |
observer_list_->RemoveObserver(observer); |
} |
+void NSSCertDatabase::AddSource(CertDatabaseSource* source) { |
+ source->AddObserver(this->notifier_.get()); |
+} |
+ |
void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { |
observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); |
} |