Index: net/base/default_server_bound_cert_store.cc |
diff --git a/net/base/default_server_bound_cert_store.cc b/net/base/default_server_bound_cert_store.cc |
index 05cd82687b2db36509aff45b7f8f50e572b0484a..d4dd1d09158038dbc75aabf15e8f82dbf4efde5a 100644 |
--- a/net/base/default_server_bound_cert_store.cc |
+++ b/net/base/default_server_bound_cert_store.cc |
@@ -6,16 +6,235 @@ |
#include "base/bind.h" |
#include "base/message_loop.h" |
+#include "base/metrics/histogram.h" |
namespace net { |
+// -------------------------------------------------------------------------- |
+// Task |
+class DefaultServerBoundCertStore::Task { |
+ public: |
+ virtual ~Task(); |
+ |
+ // Runs the task and invokes the client callback on the thread that |
+ // originally constructed the task. |
+ virtual void Run(DefaultServerBoundCertStore* store) = 0; |
+ |
+ protected: |
+ void InvokeCallback(base::Closure callback) const; |
+}; |
+ |
+DefaultServerBoundCertStore::Task::~Task() { |
+} |
+ |
+void DefaultServerBoundCertStore::Task::InvokeCallback( |
+ base::Closure callback) const { |
+ if (!callback.is_null()) |
+ callback.Run(); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// GetServerBoundCertTask |
+class DefaultServerBoundCertStore::GetServerBoundCertTask |
+ : public DefaultServerBoundCertStore::Task { |
+ public: |
+ GetServerBoundCertTask(const std::string& server_identifier, |
+ const GetCertCallback& callback); |
+ virtual ~GetServerBoundCertTask(); |
+ virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ GetCertCallback callback_; |
+}; |
+ |
+DefaultServerBoundCertStore::GetServerBoundCertTask::GetServerBoundCertTask( |
+ const std::string& server_identifier, |
+ const GetCertCallback& callback) |
+ : server_identifier_(server_identifier), |
+ callback_(callback) { |
+} |
+ |
+DefaultServerBoundCertStore::GetServerBoundCertTask::~GetServerBoundCertTask() { |
+} |
+ |
+void DefaultServerBoundCertStore::GetServerBoundCertTask::Run( |
+ DefaultServerBoundCertStore* store) { |
+ SSLClientCertType type = CLIENT_CERT_INVALID_TYPE; |
+ base::Time expiration_time; |
+ std::string private_key_result; |
+ std::string cert_result; |
+ bool was_sync = store->GetServerBoundCert( |
+ server_identifier_, &type, &expiration_time, &private_key_result, |
+ &cert_result, GetCertCallback()); |
+ DCHECK(was_sync); |
+ |
+ InvokeCallback(base::Bind(callback_, server_identifier_, type, |
+ expiration_time, private_key_result, cert_result)); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// SetServerBoundCertTask |
+class DefaultServerBoundCertStore::SetServerBoundCertTask |
+ : public DefaultServerBoundCertStore::Task { |
+ public: |
+ SetServerBoundCertTask(const std::string& server_identifier, |
+ SSLClientCertType type, |
+ base::Time creation_time, |
+ base::Time expiration_time, |
+ const std::string& private_key, |
+ const std::string& cert); |
+ virtual ~SetServerBoundCertTask(); |
+ virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ SSLClientCertType type_; |
+ base::Time creation_time_; |
+ base::Time expiration_time_; |
+ std::string private_key_; |
+ std::string cert_; |
+}; |
+ |
+DefaultServerBoundCertStore::SetServerBoundCertTask::SetServerBoundCertTask( |
+ const std::string& server_identifier, |
+ SSLClientCertType type, |
+ base::Time creation_time, |
+ base::Time expiration_time, |
+ const std::string& private_key, |
+ const std::string& cert) |
+ : server_identifier_(server_identifier), |
+ type_(type), |
+ creation_time_(creation_time), |
+ expiration_time_(expiration_time), |
+ private_key_(private_key), |
+ cert_(cert) { |
+} |
+ |
+DefaultServerBoundCertStore::SetServerBoundCertTask::~SetServerBoundCertTask() { |
+} |
+ |
+void DefaultServerBoundCertStore::SetServerBoundCertTask::Run( |
+ DefaultServerBoundCertStore* store) { |
+ store->SyncSetServerBoundCert(server_identifier_, type_, creation_time_, |
+ expiration_time_, private_key_, cert_); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// DeleteServerBoundCertTask |
+class DefaultServerBoundCertStore::DeleteServerBoundCertTask |
+ : public DefaultServerBoundCertStore::Task { |
+ public: |
+ DeleteServerBoundCertTask(const std::string& server_identifier, |
+ const base::Closure& callback); |
+ virtual ~DeleteServerBoundCertTask(); |
+ virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ base::Closure callback_; |
+}; |
+ |
+DefaultServerBoundCertStore::DeleteServerBoundCertTask:: |
+ DeleteServerBoundCertTask( |
+ const std::string& server_identifier, |
+ const base::Closure& callback) |
+ : server_identifier_(server_identifier), |
+ callback_(callback) { |
+} |
+ |
+DefaultServerBoundCertStore::DeleteServerBoundCertTask:: |
+ ~DeleteServerBoundCertTask() { |
+} |
+ |
+void DefaultServerBoundCertStore::DeleteServerBoundCertTask::Run( |
+ DefaultServerBoundCertStore* store) { |
+ store->SyncDeleteServerBoundCert(server_identifier_); |
+ |
+ InvokeCallback(callback_); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// DeleteAllCreatedBetweenTask |
+class DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask |
+ : public DefaultServerBoundCertStore::Task { |
+ public: |
+ DeleteAllCreatedBetweenTask(base::Time delete_begin, |
+ base::Time delete_end, |
+ const base::Closure& callback); |
+ virtual ~DeleteAllCreatedBetweenTask(); |
+ virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE; |
+ |
+ private: |
+ base::Time delete_begin_; |
+ base::Time delete_end_; |
+ base::Closure callback_; |
+}; |
+ |
+DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask:: |
+ DeleteAllCreatedBetweenTask( |
+ base::Time delete_begin, |
+ base::Time delete_end, |
+ const base::Closure& callback) |
+ : delete_begin_(delete_begin), |
+ delete_end_(delete_end), |
+ callback_(callback) { |
+} |
+ |
+DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask:: |
+ ~DeleteAllCreatedBetweenTask() { |
+} |
+ |
+void DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::Run( |
+ DefaultServerBoundCertStore* store) { |
+ store->SyncDeleteAllCreatedBetween(delete_begin_, delete_end_); |
+ |
+ InvokeCallback(callback_); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// GetAllServerBoundCertsTask |
+class DefaultServerBoundCertStore::GetAllServerBoundCertsTask |
+ : public DefaultServerBoundCertStore::Task { |
+ public: |
+ explicit GetAllServerBoundCertsTask(const GetCertListCallback& callback); |
+ virtual ~GetAllServerBoundCertsTask(); |
+ virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ GetCertListCallback callback_; |
+}; |
+ |
+DefaultServerBoundCertStore::GetAllServerBoundCertsTask:: |
+ GetAllServerBoundCertsTask(const GetCertListCallback& callback) |
+ : callback_(callback) { |
+} |
+ |
+DefaultServerBoundCertStore::GetAllServerBoundCertsTask:: |
+ ~GetAllServerBoundCertsTask() { |
+} |
+ |
+void DefaultServerBoundCertStore::GetAllServerBoundCertsTask::Run( |
+ DefaultServerBoundCertStore* store) { |
+ ServerBoundCertList cert_list; |
+ store->SyncGetAllServerBoundCerts(&cert_list); |
+ |
+ InvokeCallback(base::Bind(callback_, cert_list)); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// DefaultServerBoundCertStore |
+ |
// static |
const size_t DefaultServerBoundCertStore::kMaxCerts = 3300; |
DefaultServerBoundCertStore::DefaultServerBoundCertStore( |
PersistentStore* store) |
: initialized_(false), |
- store_(store) {} |
+ loaded_(false), |
+ store_(store), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {} |
void DefaultServerBoundCertStore::FlushStore( |
const base::Closure& completion_task) { |
@@ -30,21 +249,28 @@ void DefaultServerBoundCertStore::FlushStore( |
bool DefaultServerBoundCertStore::GetServerBoundCert( |
const std::string& server_identifier, |
SSLClientCertType* type, |
- base::Time* creation_time, |
base::Time* expiration_time, |
std::string* private_key_result, |
- std::string* cert_result) { |
+ std::string* cert_result, |
+ const GetCertCallback& callback) { |
DCHECK(CalledOnValidThread()); |
InitIfNecessary(); |
+ if (!loaded_) { |
+ EnqueueTask(scoped_ptr<Task>( |
+ new GetServerBoundCertTask(server_identifier, callback))); |
+ return false; |
+ } |
+ |
ServerBoundCertMap::iterator it = server_bound_certs_.find(server_identifier); |
- if (it == server_bound_certs_.end()) |
- return false; |
+ if (it == server_bound_certs_.end()) { |
+ *type = CLIENT_CERT_INVALID_TYPE; |
+ return true; |
+ } |
ServerBoundCert* cert = it->second; |
*type = cert->type(); |
- *creation_time = cert->creation_time(); |
*expiration_time = cert->expiration_time(); |
*private_key_result = cert->private_key(); |
*cert_result = cert->cert(); |
@@ -59,61 +285,38 @@ void DefaultServerBoundCertStore::SetServerBoundCert( |
base::Time expiration_time, |
const std::string& private_key, |
const std::string& cert) { |
- DCHECK(CalledOnValidThread()); |
- InitIfNecessary(); |
- |
- InternalDeleteServerBoundCert(server_identifier); |
- InternalInsertServerBoundCert( |
- server_identifier, |
- new ServerBoundCert( |
- server_identifier, type, creation_time, expiration_time, private_key, |
- cert)); |
+ RunOrEnqueueTask(scoped_ptr<Task>(new SetServerBoundCertTask( |
+ server_identifier, type, creation_time, expiration_time, private_key, |
+ cert))); |
} |
void DefaultServerBoundCertStore::DeleteServerBoundCert( |
- const std::string& server_identifier) { |
- DCHECK(CalledOnValidThread()); |
- InitIfNecessary(); |
- InternalDeleteServerBoundCert(server_identifier); |
+ const std::string& server_identifier, |
+ const base::Closure& callback) { |
+ RunOrEnqueueTask(scoped_ptr<Task>( |
+ new DeleteServerBoundCertTask(server_identifier, callback))); |
} |
void DefaultServerBoundCertStore::DeleteAllCreatedBetween( |
base::Time delete_begin, |
- base::Time delete_end) { |
- DCHECK(CalledOnValidThread()); |
- InitIfNecessary(); |
- for (ServerBoundCertMap::iterator it = server_bound_certs_.begin(); |
- it != server_bound_certs_.end();) { |
- ServerBoundCertMap::iterator cur = it; |
- ++it; |
- ServerBoundCert* cert = cur->second; |
- if ((delete_begin.is_null() || cert->creation_time() >= delete_begin) && |
- (delete_end.is_null() || cert->creation_time() < delete_end)) { |
- if (store_) |
- store_->DeleteServerBoundCert(*cert); |
- delete cert; |
- server_bound_certs_.erase(cur); |
- } |
- } |
+ base::Time delete_end, |
+ const base::Closure& callback) { |
+ RunOrEnqueueTask(scoped_ptr<Task>( |
+ new DeleteAllCreatedBetweenTask(delete_begin, delete_end, callback))); |
} |
-void DefaultServerBoundCertStore::DeleteAll() { |
- DeleteAllCreatedBetween(base::Time(), base::Time()); |
+void DefaultServerBoundCertStore::DeleteAll( |
+ const base::Closure& callback) { |
+ DeleteAllCreatedBetween(base::Time(), base::Time(), callback); |
} |
void DefaultServerBoundCertStore::GetAllServerBoundCerts( |
- ServerBoundCertList* server_bound_certs) { |
- DCHECK(CalledOnValidThread()); |
- InitIfNecessary(); |
- for (ServerBoundCertMap::iterator it = server_bound_certs_.begin(); |
- it != server_bound_certs_.end(); ++it) { |
- server_bound_certs->push_back(*it->second); |
- } |
+ const GetCertListCallback& callback) { |
+ RunOrEnqueueTask(scoped_ptr<Task>(new GetAllServerBoundCertsTask(callback))); |
} |
int DefaultServerBoundCertStore::GetCertCount() { |
DCHECK(CalledOnValidThread()); |
- InitIfNecessary(); |
return server_bound_certs_.size(); |
} |
@@ -143,23 +346,123 @@ void DefaultServerBoundCertStore::DeleteAllInMemory() { |
void DefaultServerBoundCertStore::InitStore() { |
DCHECK(CalledOnValidThread()); |
DCHECK(store_) << "Store must exist to initialize"; |
+ DCHECK(!loaded_); |
+ |
+ store_->Load(base::Bind(&DefaultServerBoundCertStore::OnLoaded, |
+ weak_ptr_factory_.GetWeakPtr())); |
+} |
- // Initialize the store and sync in any saved persistent certs. |
- std::vector<ServerBoundCert*> certs; |
- // Reserve space for the maximum amount of certs a database should have. |
- // This prevents multiple vector growth / copies as we append certs. |
- certs.reserve(kMaxCerts); |
- store_->Load(&certs); |
+void DefaultServerBoundCertStore::OnLoaded( |
+ scoped_ptr<ScopedVector<ServerBoundCert> > certs) { |
+ DCHECK(CalledOnValidThread()); |
- for (std::vector<ServerBoundCert*>::const_iterator it = certs.begin(); |
- it != certs.end(); ++it) { |
+ for (std::vector<ServerBoundCert*>::const_iterator it = certs->begin(); |
+ it != certs->end(); ++it) { |
+ DCHECK(server_bound_certs_.find((*it)->server_identifier()) == |
+ server_bound_certs_.end()); |
server_bound_certs_[(*it)->server_identifier()] = *it; |
} |
+ certs->weak_clear(); |
+ |
+ loaded_ = true; |
+ |
+ base::TimeDelta wait_time; |
+ if (!waiting_tasks_.empty()) |
+ wait_time = base::TimeTicks::Now() - waiting_tasks_start_time_; |
+ DVLOG(1) << "Task delay " << wait_time.InMilliseconds(); |
+ UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.TaskMaxWaitTime", |
+ wait_time, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(1), |
+ 50); |
+ UMA_HISTOGRAM_COUNTS_100("DomainBoundCerts.TaskWaitCount", |
+ waiting_tasks_.size()); |
+ |
+ |
+ for (ScopedVector<Task>::iterator i = waiting_tasks_.begin(); |
+ i != waiting_tasks_.end(); ++i) |
+ (*i)->Run(this); |
+ waiting_tasks_.clear(); |
+} |
+ |
+void DefaultServerBoundCertStore::SyncSetServerBoundCert( |
+ const std::string& server_identifier, |
+ SSLClientCertType type, |
+ base::Time creation_time, |
+ base::Time expiration_time, |
+ const std::string& private_key, |
+ const std::string& cert) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ |
+ InternalDeleteServerBoundCert(server_identifier); |
+ InternalInsertServerBoundCert( |
+ server_identifier, |
+ new ServerBoundCert( |
+ server_identifier, type, creation_time, expiration_time, private_key, |
+ cert)); |
+} |
+ |
+void DefaultServerBoundCertStore::SyncDeleteServerBoundCert( |
+ const std::string& server_identifier) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ InternalDeleteServerBoundCert(server_identifier); |
+} |
+ |
+void DefaultServerBoundCertStore::SyncDeleteAllCreatedBetween( |
+ base::Time delete_begin, |
+ base::Time delete_end) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ for (ServerBoundCertMap::iterator it = server_bound_certs_.begin(); |
+ it != server_bound_certs_.end();) { |
+ ServerBoundCertMap::iterator cur = it; |
+ ++it; |
+ ServerBoundCert* cert = cur->second; |
+ if ((delete_begin.is_null() || cert->creation_time() >= delete_begin) && |
+ (delete_end.is_null() || cert->creation_time() < delete_end)) { |
+ if (store_) |
+ store_->DeleteServerBoundCert(*cert); |
+ delete cert; |
+ server_bound_certs_.erase(cur); |
+ } |
+ } |
+} |
+ |
+void DefaultServerBoundCertStore::SyncGetAllServerBoundCerts( |
+ ServerBoundCertList* cert_list) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ for (ServerBoundCertMap::iterator it = server_bound_certs_.begin(); |
+ it != server_bound_certs_.end(); ++it) |
+ cert_list->push_back(*it->second); |
+} |
+ |
+void DefaultServerBoundCertStore::EnqueueTask(scoped_ptr<Task> task) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(!loaded_); |
+ if (waiting_tasks_.empty()) |
+ waiting_tasks_start_time_ = base::TimeTicks::Now(); |
+ waiting_tasks_.push_back(task.release()); |
+} |
+ |
+void DefaultServerBoundCertStore::RunOrEnqueueTask(scoped_ptr<Task> task) { |
+ DCHECK(CalledOnValidThread()); |
+ InitIfNecessary(); |
+ |
+ if (!loaded_) { |
+ EnqueueTask(task.Pass()); |
+ return; |
+ } |
+ |
+ task->Run(this); |
} |
void DefaultServerBoundCertStore::InternalDeleteServerBoundCert( |
const std::string& server_identifier) { |
DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
ServerBoundCertMap::iterator it = server_bound_certs_.find(server_identifier); |
if (it == server_bound_certs_.end()) |
@@ -176,6 +479,7 @@ void DefaultServerBoundCertStore::InternalInsertServerBoundCert( |
const std::string& server_identifier, |
ServerBoundCert* cert) { |
DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
if (store_) |
store_->AddServerBoundCert(*cert); |