Index: net/cert/nss_cert_database.cc |
diff --git a/net/cert/nss_cert_database.cc b/net/cert/nss_cert_database.cc |
index ed861b200bfeb207ee1fa6ff2fe75a9a72bb429c..c1fc4f9d0cca66473b792a447aeb846fd8b15a24 100644 |
--- a/net/cert/nss_cert_database.cc |
+++ b/net/cert/nss_cert_database.cc |
@@ -17,6 +17,7 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/observer_list_threadsafe.h" |
#include "base/task_runner.h" |
+#include "base/task_runner_util.h" |
#include "base/threading/worker_pool.h" |
#include "crypto/nss_util.h" |
#include "crypto/nss_util_internal.h" |
@@ -65,7 +66,8 @@ NSSCertDatabase* NSSCertDatabase::GetInstance() { |
} |
NSSCertDatabase::NSSCertDatabase() |
- : observer_list_(new ObserverListThreadSafe<Observer>) { |
+ : observer_list_(new ObserverListThreadSafe<Observer>), |
+ weak_factory_(this) { |
// This also makes sure that NSS has been initialized. |
CertDatabase::GetInstance()->ObserveNSSCertDatabase(this); |
@@ -75,18 +77,34 @@ NSSCertDatabase::NSSCertDatabase() |
NSSCertDatabase::~NSSCertDatabase() {} |
void NSSCertDatabase::ListCertsSync(CertificateList* certs) { |
- ListCertsImpl(certs); |
+ ListCertsImpl(crypto::ScopedPK11Slot(), certs); |
} |
void NSSCertDatabase::ListCerts( |
const base::Callback<void(scoped_ptr<CertificateList> certs)>& callback) { |
scoped_ptr<CertificateList> certs(new CertificateList()); |
- // base::Pased will NULL out |certs|, so cache the underlying pointer here. |
+ // base::Passed will NULL out |certs|, so cache the underlying pointer here. |
CertificateList* raw_certs = certs.get(); |
GetSlowTaskRunner()->PostTaskAndReply( |
FROM_HERE, |
base::Bind(&NSSCertDatabase::ListCertsImpl, |
+ base::Passed(crypto::ScopedPK11Slot()), |
+ base::Unretained(raw_certs)), |
+ base::Bind(callback, base::Passed(&certs))); |
+} |
+ |
+void NSSCertDatabase::ListCertsInSlot(const ListCertsCallback& callback, |
+ PK11SlotInfo* slot) { |
+ DCHECK(slot); |
+ scoped_ptr<CertificateList> certs(new CertificateList()); |
+ |
+ // base::Passed will NULL out |certs|, so cache the underlying pointer here. |
+ CertificateList* raw_certs = certs.get(); |
+ GetSlowTaskRunner()->PostTaskAndReply( |
+ FROM_HERE, |
+ base::Bind(&NSSCertDatabase::ListCertsImpl, |
+ base::Passed(crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot))), |
base::Unretained(raw_certs)), |
base::Bind(callback, base::Passed(&certs))); |
} |
@@ -313,31 +331,26 @@ bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, |
return success; |
} |
-bool NSSCertDatabase::DeleteCertAndKey(const X509Certificate* cert) { |
- // For some reason, PK11_DeleteTokenCertAndKey only calls |
- // SEC_DeletePermCertificate if the private key is found. So, we check |
- // whether a private key exists before deciding which function to call to |
- // delete the cert. |
- SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(), |
- NULL); |
- if (privKey) { |
- SECKEY_DestroyPrivateKey(privKey); |
- if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { |
- LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); |
- return false; |
- } |
- } else { |
- if (SEC_DeletePermCertificate(cert->os_cert_handle())) { |
- LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); |
- return false; |
- } |
- } |
- |
+bool NSSCertDatabase::DeleteCertAndKey(X509Certificate* cert) { |
+ if (!DeleteCertAndKeyImpl(cert)) |
+ return false; |
NotifyObserversOfCertRemoved(cert); |
- |
return true; |
} |
+void NSSCertDatabase::DeleteCertAndKeyAsync( |
+ const scoped_refptr<X509Certificate>& cert, |
+ const DeleteCertCallback& callback) { |
+ base::PostTaskAndReplyWithResult( |
+ GetSlowTaskRunner().get(), |
+ FROM_HERE, |
+ base::Bind(&NSSCertDatabase::DeleteCertAndKeyImpl, cert), |
+ base::Bind(&NSSCertDatabase::NotifyCertRemovalAndCallBack, |
+ weak_factory_.GetWeakPtr(), |
+ cert, |
+ callback)); |
+} |
+ |
bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const { |
PK11SlotInfo* slot = cert->os_cert_handle()->slot; |
return slot && PK11_IsReadOnly(slot); |
@@ -362,13 +375,18 @@ void NSSCertDatabase::SetSlowTaskRunnerForTest( |
} |
// static |
-void NSSCertDatabase::ListCertsImpl(CertificateList* certs) { |
+void NSSCertDatabase::ListCertsImpl(crypto::ScopedPK11Slot slot, |
+ CertificateList* certs) { |
certs->clear(); |
- CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); |
+ CERTCertList* cert_list = NULL; |
+ if (slot) |
+ cert_list = PK11_ListCertsInSlot(slot.get()); |
+ else |
+ cert_list = PK11_ListCerts(PK11CertListUnique, NULL); |
+ |
CERTCertListNode* node; |
- for (node = CERT_LIST_HEAD(cert_list); |
- !CERT_LIST_END(node, cert_list); |
+ for (node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); |
node = CERT_LIST_NEXT(node)) { |
certs->push_back(X509Certificate::CreateFromHandle( |
node->cert, X509Certificate::OSCertHandles())); |
@@ -382,6 +400,15 @@ scoped_refptr<base::TaskRunner> NSSCertDatabase::GetSlowTaskRunner() const { |
return base::WorkerPool::GetTaskRunner(true /*task is slow*/); |
} |
+void NSSCertDatabase::NotifyCertRemovalAndCallBack( |
+ scoped_refptr<X509Certificate> cert, |
+ const DeleteCertCallback& callback, |
+ bool success) { |
+ if (success) |
+ NotifyObserversOfCertRemoved(cert); |
+ callback.Run(success); |
+} |
+ |
void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { |
observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); |
} |
@@ -397,4 +424,28 @@ void NSSCertDatabase::NotifyObserversOfCACertChanged( |
&Observer::OnCACertChanged, make_scoped_refptr(cert)); |
} |
+// static |
+bool NSSCertDatabase::DeleteCertAndKeyImpl( |
+ scoped_refptr<X509Certificate> cert) { |
+ // For some reason, PK11_DeleteTokenCertAndKey only calls |
+ // SEC_DeletePermCertificate if the private key is found. So, we check |
+ // whether a private key exists before deciding which function to call to |
+ // delete the cert. |
+ SECKEYPrivateKey* privKey = |
+ PK11_FindKeyByAnyCert(cert->os_cert_handle(), NULL); |
+ if (privKey) { |
+ SECKEY_DestroyPrivateKey(privKey); |
+ if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { |
+ LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); |
+ return false; |
+ } |
+ } else { |
+ if (SEC_DeletePermCertificate(cert->os_cert_handle())) { |
+ LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
} // namespace net |