Index: net/ssl/default_channel_id_store.cc |
diff --git a/net/ssl/default_channel_id_store.cc b/net/ssl/default_channel_id_store.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..92e30016dae7d0f9152e8bcadc4775a1054dfc74 |
--- /dev/null |
+++ b/net/ssl/default_channel_id_store.cc |
@@ -0,0 +1,471 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/ssl/default_channel_id_store.h" |
+ |
+#include "base/bind.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/metrics/histogram.h" |
+#include "net/base/net_errors.h" |
+ |
+namespace net { |
+ |
+// -------------------------------------------------------------------------- |
+// Task |
+class DefaultChannelIDStore::Task { |
+ public: |
+ virtual ~Task(); |
+ |
+ // Runs the task and invokes the client callback on the thread that |
+ // originally constructed the task. |
+ virtual void Run(DefaultChannelIDStore* store) = 0; |
+ |
+ protected: |
+ void InvokeCallback(base::Closure callback) const; |
+}; |
+ |
+DefaultChannelIDStore::Task::~Task() { |
+} |
+ |
+void DefaultChannelIDStore::Task::InvokeCallback( |
+ base::Closure callback) const { |
+ if (!callback.is_null()) |
+ callback.Run(); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// GetChannelIDTask |
+class DefaultChannelIDStore::GetChannelIDTask |
+ : public DefaultChannelIDStore::Task { |
+ public: |
+ GetChannelIDTask(const std::string& server_identifier, |
+ const GetChannelIDCallback& callback); |
+ virtual ~GetChannelIDTask(); |
+ virtual void Run(DefaultChannelIDStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ GetChannelIDCallback callback_; |
+}; |
+ |
+DefaultChannelIDStore::GetChannelIDTask::GetChannelIDTask( |
+ const std::string& server_identifier, |
+ const GetChannelIDCallback& callback) |
+ : server_identifier_(server_identifier), |
+ callback_(callback) { |
+} |
+ |
+DefaultChannelIDStore::GetChannelIDTask::~GetChannelIDTask() { |
+} |
+ |
+void DefaultChannelIDStore::GetChannelIDTask::Run( |
+ DefaultChannelIDStore* store) { |
+ base::Time expiration_time; |
+ std::string private_key_result; |
+ std::string cert_result; |
+ int err = store->GetChannelID( |
+ server_identifier_, &expiration_time, &private_key_result, |
+ &cert_result, GetChannelIDCallback()); |
+ DCHECK(err != ERR_IO_PENDING); |
+ |
+ InvokeCallback(base::Bind(callback_, err, server_identifier_, |
+ expiration_time, private_key_result, cert_result)); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// SetChannelIDTask |
+class DefaultChannelIDStore::SetChannelIDTask |
+ : public DefaultChannelIDStore::Task { |
+ public: |
+ SetChannelIDTask(const std::string& server_identifier, |
+ base::Time creation_time, |
+ base::Time expiration_time, |
+ const std::string& private_key, |
+ const std::string& cert); |
+ virtual ~SetChannelIDTask(); |
+ virtual void Run(DefaultChannelIDStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ base::Time creation_time_; |
+ base::Time expiration_time_; |
+ std::string private_key_; |
+ std::string cert_; |
+}; |
+ |
+DefaultChannelIDStore::SetChannelIDTask::SetChannelIDTask( |
+ const std::string& server_identifier, |
+ base::Time creation_time, |
+ base::Time expiration_time, |
+ const std::string& private_key, |
+ const std::string& cert) |
+ : server_identifier_(server_identifier), |
+ creation_time_(creation_time), |
+ expiration_time_(expiration_time), |
+ private_key_(private_key), |
+ cert_(cert) { |
+} |
+ |
+DefaultChannelIDStore::SetChannelIDTask::~SetChannelIDTask() { |
+} |
+ |
+void DefaultChannelIDStore::SetChannelIDTask::Run( |
+ DefaultChannelIDStore* store) { |
+ store->SyncSetChannelID(server_identifier_, creation_time_, |
+ expiration_time_, private_key_, cert_); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// DeleteChannelIDTask |
+class DefaultChannelIDStore::DeleteChannelIDTask |
+ : public DefaultChannelIDStore::Task { |
+ public: |
+ DeleteChannelIDTask(const std::string& server_identifier, |
+ const base::Closure& callback); |
+ virtual ~DeleteChannelIDTask(); |
+ virtual void Run(DefaultChannelIDStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ base::Closure callback_; |
+}; |
+ |
+DefaultChannelIDStore::DeleteChannelIDTask:: |
+ DeleteChannelIDTask( |
+ const std::string& server_identifier, |
+ const base::Closure& callback) |
+ : server_identifier_(server_identifier), |
+ callback_(callback) { |
+} |
+ |
+DefaultChannelIDStore::DeleteChannelIDTask:: |
+ ~DeleteChannelIDTask() { |
+} |
+ |
+void DefaultChannelIDStore::DeleteChannelIDTask::Run( |
+ DefaultChannelIDStore* store) { |
+ store->SyncDeleteChannelID(server_identifier_); |
+ |
+ InvokeCallback(callback_); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// DeleteAllCreatedBetweenTask |
+class DefaultChannelIDStore::DeleteAllCreatedBetweenTask |
+ : public DefaultChannelIDStore::Task { |
+ public: |
+ DeleteAllCreatedBetweenTask(base::Time delete_begin, |
+ base::Time delete_end, |
+ const base::Closure& callback); |
+ virtual ~DeleteAllCreatedBetweenTask(); |
+ virtual void Run(DefaultChannelIDStore* store) OVERRIDE; |
+ |
+ private: |
+ base::Time delete_begin_; |
+ base::Time delete_end_; |
+ base::Closure callback_; |
+}; |
+ |
+DefaultChannelIDStore::DeleteAllCreatedBetweenTask:: |
+ DeleteAllCreatedBetweenTask( |
+ base::Time delete_begin, |
+ base::Time delete_end, |
+ const base::Closure& callback) |
+ : delete_begin_(delete_begin), |
+ delete_end_(delete_end), |
+ callback_(callback) { |
+} |
+ |
+DefaultChannelIDStore::DeleteAllCreatedBetweenTask:: |
+ ~DeleteAllCreatedBetweenTask() { |
+} |
+ |
+void DefaultChannelIDStore::DeleteAllCreatedBetweenTask::Run( |
+ DefaultChannelIDStore* store) { |
+ store->SyncDeleteAllCreatedBetween(delete_begin_, delete_end_); |
+ |
+ InvokeCallback(callback_); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// GetAllChannelIDsTask |
+class DefaultChannelIDStore::GetAllChannelIDsTask |
+ : public DefaultChannelIDStore::Task { |
+ public: |
+ explicit GetAllChannelIDsTask(const GetChannelIDListCallback& callback); |
+ virtual ~GetAllChannelIDsTask(); |
+ virtual void Run(DefaultChannelIDStore* store) OVERRIDE; |
+ |
+ private: |
+ std::string server_identifier_; |
+ GetChannelIDListCallback callback_; |
+}; |
+ |
+DefaultChannelIDStore::GetAllChannelIDsTask:: |
+ GetAllChannelIDsTask(const GetChannelIDListCallback& callback) |
+ : callback_(callback) { |
+} |
+ |
+DefaultChannelIDStore::GetAllChannelIDsTask:: |
+ ~GetAllChannelIDsTask() { |
+} |
+ |
+void DefaultChannelIDStore::GetAllChannelIDsTask::Run( |
+ DefaultChannelIDStore* store) { |
+ ChannelIDList cert_list; |
+ store->SyncGetAllChannelIDs(&cert_list); |
+ |
+ InvokeCallback(base::Bind(callback_, cert_list)); |
+} |
+ |
+// -------------------------------------------------------------------------- |
+// DefaultChannelIDStore |
+ |
+DefaultChannelIDStore::DefaultChannelIDStore( |
+ PersistentStore* store) |
+ : initialized_(false), |
+ loaded_(false), |
+ store_(store), |
+ weak_ptr_factory_(this) {} |
+ |
+int DefaultChannelIDStore::GetChannelID( |
+ const std::string& server_identifier, |
+ base::Time* expiration_time, |
+ std::string* private_key_result, |
+ std::string* cert_result, |
+ const GetChannelIDCallback& callback) { |
+ DCHECK(CalledOnValidThread()); |
+ InitIfNecessary(); |
+ |
+ if (!loaded_) { |
+ EnqueueTask(scoped_ptr<Task>( |
+ new GetChannelIDTask(server_identifier, callback))); |
+ return ERR_IO_PENDING; |
+ } |
+ |
+ ChannelIDMap::iterator it = channel_ids_.find(server_identifier); |
+ |
+ if (it == channel_ids_.end()) |
+ return ERR_FILE_NOT_FOUND; |
+ |
+ ChannelID* channel_id = it->second; |
+ *expiration_time = channel_id->expiration_time(); |
+ *private_key_result = channel_id->private_key(); |
+ *cert_result = channel_id->cert(); |
+ |
+ return OK; |
+} |
+ |
+void DefaultChannelIDStore::SetChannelID( |
+ const std::string& server_identifier, |
+ base::Time creation_time, |
+ base::Time expiration_time, |
+ const std::string& private_key, |
+ const std::string& cert) { |
+ RunOrEnqueueTask(scoped_ptr<Task>(new SetChannelIDTask( |
+ server_identifier, creation_time, expiration_time, private_key, |
+ cert))); |
+} |
+ |
+void DefaultChannelIDStore::DeleteChannelID( |
+ const std::string& server_identifier, |
+ const base::Closure& callback) { |
+ RunOrEnqueueTask(scoped_ptr<Task>( |
+ new DeleteChannelIDTask(server_identifier, callback))); |
+} |
+ |
+void DefaultChannelIDStore::DeleteAllCreatedBetween( |
+ base::Time delete_begin, |
+ base::Time delete_end, |
+ const base::Closure& callback) { |
+ RunOrEnqueueTask(scoped_ptr<Task>( |
+ new DeleteAllCreatedBetweenTask(delete_begin, delete_end, callback))); |
+} |
+ |
+void DefaultChannelIDStore::DeleteAll( |
+ const base::Closure& callback) { |
+ DeleteAllCreatedBetween(base::Time(), base::Time(), callback); |
+} |
+ |
+void DefaultChannelIDStore::GetAllChannelIDs( |
+ const GetChannelIDListCallback& callback) { |
+ RunOrEnqueueTask(scoped_ptr<Task>(new GetAllChannelIDsTask(callback))); |
+} |
+ |
+int DefaultChannelIDStore::GetChannelIDCount() { |
+ DCHECK(CalledOnValidThread()); |
+ |
+ return channel_ids_.size(); |
+} |
+ |
+void DefaultChannelIDStore::SetForceKeepSessionState() { |
+ DCHECK(CalledOnValidThread()); |
+ InitIfNecessary(); |
+ |
+ if (store_.get()) |
+ store_->SetForceKeepSessionState(); |
+} |
+ |
+DefaultChannelIDStore::~DefaultChannelIDStore() { |
+ DeleteAllInMemory(); |
+} |
+ |
+void DefaultChannelIDStore::DeleteAllInMemory() { |
+ DCHECK(CalledOnValidThread()); |
+ |
+ for (ChannelIDMap::iterator it = channel_ids_.begin(); |
+ it != channel_ids_.end(); ++it) { |
+ delete it->second; |
+ } |
+ channel_ids_.clear(); |
+} |
+ |
+void DefaultChannelIDStore::InitStore() { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(store_.get()) << "Store must exist to initialize"; |
+ DCHECK(!loaded_); |
+ |
+ store_->Load(base::Bind(&DefaultChannelIDStore::OnLoaded, |
+ weak_ptr_factory_.GetWeakPtr())); |
+} |
+ |
+void DefaultChannelIDStore::OnLoaded( |
+ scoped_ptr<ScopedVector<ChannelID> > channel_ids) { |
+ DCHECK(CalledOnValidThread()); |
+ |
+ for (std::vector<ChannelID*>::const_iterator it = channel_ids->begin(); |
+ it != channel_ids->end(); ++it) { |
+ DCHECK(channel_ids_.find((*it)->server_identifier()) == |
+ channel_ids_.end()); |
+ channel_ids_[(*it)->server_identifier()] = *it; |
+ } |
+ channel_ids->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 DefaultChannelIDStore::SyncSetChannelID( |
+ const std::string& server_identifier, |
+ base::Time creation_time, |
+ base::Time expiration_time, |
+ const std::string& private_key, |
+ const std::string& cert) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ |
+ InternalDeleteChannelID(server_identifier); |
+ InternalInsertChannelID( |
+ server_identifier, |
+ new ChannelID( |
+ server_identifier, creation_time, expiration_time, private_key, |
+ cert)); |
+} |
+ |
+void DefaultChannelIDStore::SyncDeleteChannelID( |
+ const std::string& server_identifier) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ InternalDeleteChannelID(server_identifier); |
+} |
+ |
+void DefaultChannelIDStore::SyncDeleteAllCreatedBetween( |
+ base::Time delete_begin, |
+ base::Time delete_end) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ for (ChannelIDMap::iterator it = channel_ids_.begin(); |
+ it != channel_ids_.end();) { |
+ ChannelIDMap::iterator cur = it; |
+ ++it; |
+ ChannelID* channel_id = cur->second; |
+ if ((delete_begin.is_null() || |
+ channel_id->creation_time() >= delete_begin) && |
+ (delete_end.is_null() || channel_id->creation_time() < delete_end)) { |
+ if (store_.get()) |
+ store_->DeleteChannelID(*channel_id); |
+ delete channel_id; |
+ channel_ids_.erase(cur); |
+ } |
+ } |
+} |
+ |
+void DefaultChannelIDStore::SyncGetAllChannelIDs( |
+ ChannelIDList* channel_id_list) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ for (ChannelIDMap::iterator it = channel_ids_.begin(); |
+ it != channel_ids_.end(); ++it) |
+ channel_id_list->push_back(*it->second); |
+} |
+ |
+void DefaultChannelIDStore::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 DefaultChannelIDStore::RunOrEnqueueTask(scoped_ptr<Task> task) { |
+ DCHECK(CalledOnValidThread()); |
+ InitIfNecessary(); |
+ |
+ if (!loaded_) { |
+ EnqueueTask(task.Pass()); |
+ return; |
+ } |
+ |
+ task->Run(this); |
+} |
+ |
+void DefaultChannelIDStore::InternalDeleteChannelID( |
+ const std::string& server_identifier) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ |
+ ChannelIDMap::iterator it = channel_ids_.find(server_identifier); |
+ if (it == channel_ids_.end()) |
+ return; // There is nothing to delete. |
+ |
+ ChannelID* channel_id = it->second; |
+ if (store_.get()) |
+ store_->DeleteChannelID(*channel_id); |
+ channel_ids_.erase(it); |
+ delete channel_id; |
+} |
+ |
+void DefaultChannelIDStore::InternalInsertChannelID( |
+ const std::string& server_identifier, |
+ ChannelID* channel_id) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(loaded_); |
+ |
+ if (store_.get()) |
+ store_->AddChannelID(*channel_id); |
+ channel_ids_[server_identifier] = channel_id; |
+} |
+ |
+DefaultChannelIDStore::PersistentStore::PersistentStore() {} |
+ |
+DefaultChannelIDStore::PersistentStore::~PersistentStore() {} |
+ |
+} // namespace net |