1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/ssl/default_server_bound_cert_store.h"
8 #include "base/message_loop.h"
9 #include "base/metrics/histogram.h"
13 // --------------------------------------------------------------------------
15 class DefaultServerBoundCertStore::Task
{
19 // Runs the task and invokes the client callback on the thread that
20 // originally constructed the task.
21 virtual void Run(DefaultServerBoundCertStore
* store
) = 0;
24 void InvokeCallback(base::Closure callback
) const;
27 DefaultServerBoundCertStore::Task::~Task() {
30 void DefaultServerBoundCertStore::Task::InvokeCallback(
31 base::Closure callback
) const {
32 if (!callback
.is_null())
36 // --------------------------------------------------------------------------
37 // GetServerBoundCertTask
38 class DefaultServerBoundCertStore::GetServerBoundCertTask
39 : public DefaultServerBoundCertStore::Task
{
41 GetServerBoundCertTask(const std::string
& server_identifier
,
42 const GetCertCallback
& callback
);
43 virtual ~GetServerBoundCertTask();
44 virtual void Run(DefaultServerBoundCertStore
* store
) OVERRIDE
;
47 std::string server_identifier_
;
48 GetCertCallback callback_
;
51 DefaultServerBoundCertStore::GetServerBoundCertTask::GetServerBoundCertTask(
52 const std::string
& server_identifier
,
53 const GetCertCallback
& callback
)
54 : server_identifier_(server_identifier
),
58 DefaultServerBoundCertStore::GetServerBoundCertTask::~GetServerBoundCertTask() {
61 void DefaultServerBoundCertStore::GetServerBoundCertTask::Run(
62 DefaultServerBoundCertStore
* store
) {
63 SSLClientCertType type
= CLIENT_CERT_INVALID_TYPE
;
64 base::Time expiration_time
;
65 std::string private_key_result
;
66 std::string cert_result
;
67 bool was_sync
= store
->GetServerBoundCert(
68 server_identifier_
, &type
, &expiration_time
, &private_key_result
,
69 &cert_result
, GetCertCallback());
72 InvokeCallback(base::Bind(callback_
, server_identifier_
, type
,
73 expiration_time
, private_key_result
, cert_result
));
76 // --------------------------------------------------------------------------
77 // SetServerBoundCertTask
78 class DefaultServerBoundCertStore::SetServerBoundCertTask
79 : public DefaultServerBoundCertStore::Task
{
81 SetServerBoundCertTask(const std::string
& server_identifier
,
82 SSLClientCertType type
,
83 base::Time creation_time
,
84 base::Time expiration_time
,
85 const std::string
& private_key
,
86 const std::string
& cert
);
87 virtual ~SetServerBoundCertTask();
88 virtual void Run(DefaultServerBoundCertStore
* store
) OVERRIDE
;
91 std::string server_identifier_
;
92 SSLClientCertType type_
;
93 base::Time creation_time_
;
94 base::Time expiration_time_
;
95 std::string private_key_
;
99 DefaultServerBoundCertStore::SetServerBoundCertTask::SetServerBoundCertTask(
100 const std::string
& server_identifier
,
101 SSLClientCertType type
,
102 base::Time creation_time
,
103 base::Time expiration_time
,
104 const std::string
& private_key
,
105 const std::string
& cert
)
106 : server_identifier_(server_identifier
),
108 creation_time_(creation_time
),
109 expiration_time_(expiration_time
),
110 private_key_(private_key
),
114 DefaultServerBoundCertStore::SetServerBoundCertTask::~SetServerBoundCertTask() {
117 void DefaultServerBoundCertStore::SetServerBoundCertTask::Run(
118 DefaultServerBoundCertStore
* store
) {
119 store
->SyncSetServerBoundCert(server_identifier_
, type_
, creation_time_
,
120 expiration_time_
, private_key_
, cert_
);
123 // --------------------------------------------------------------------------
124 // DeleteServerBoundCertTask
125 class DefaultServerBoundCertStore::DeleteServerBoundCertTask
126 : public DefaultServerBoundCertStore::Task
{
128 DeleteServerBoundCertTask(const std::string
& server_identifier
,
129 const base::Closure
& callback
);
130 virtual ~DeleteServerBoundCertTask();
131 virtual void Run(DefaultServerBoundCertStore
* store
) OVERRIDE
;
134 std::string server_identifier_
;
135 base::Closure callback_
;
138 DefaultServerBoundCertStore::DeleteServerBoundCertTask::
139 DeleteServerBoundCertTask(
140 const std::string
& server_identifier
,
141 const base::Closure
& callback
)
142 : server_identifier_(server_identifier
),
143 callback_(callback
) {
146 DefaultServerBoundCertStore::DeleteServerBoundCertTask::
147 ~DeleteServerBoundCertTask() {
150 void DefaultServerBoundCertStore::DeleteServerBoundCertTask::Run(
151 DefaultServerBoundCertStore
* store
) {
152 store
->SyncDeleteServerBoundCert(server_identifier_
);
154 InvokeCallback(callback_
);
157 // --------------------------------------------------------------------------
158 // DeleteAllCreatedBetweenTask
159 class DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask
160 : public DefaultServerBoundCertStore::Task
{
162 DeleteAllCreatedBetweenTask(base::Time delete_begin
,
163 base::Time delete_end
,
164 const base::Closure
& callback
);
165 virtual ~DeleteAllCreatedBetweenTask();
166 virtual void Run(DefaultServerBoundCertStore
* store
) OVERRIDE
;
169 base::Time delete_begin_
;
170 base::Time delete_end_
;
171 base::Closure callback_
;
174 DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::
175 DeleteAllCreatedBetweenTask(
176 base::Time delete_begin
,
177 base::Time delete_end
,
178 const base::Closure
& callback
)
179 : delete_begin_(delete_begin
),
180 delete_end_(delete_end
),
181 callback_(callback
) {
184 DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::
185 ~DeleteAllCreatedBetweenTask() {
188 void DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::Run(
189 DefaultServerBoundCertStore
* store
) {
190 store
->SyncDeleteAllCreatedBetween(delete_begin_
, delete_end_
);
192 InvokeCallback(callback_
);
195 // --------------------------------------------------------------------------
196 // GetAllServerBoundCertsTask
197 class DefaultServerBoundCertStore::GetAllServerBoundCertsTask
198 : public DefaultServerBoundCertStore::Task
{
200 explicit GetAllServerBoundCertsTask(const GetCertListCallback
& callback
);
201 virtual ~GetAllServerBoundCertsTask();
202 virtual void Run(DefaultServerBoundCertStore
* store
) OVERRIDE
;
205 std::string server_identifier_
;
206 GetCertListCallback callback_
;
209 DefaultServerBoundCertStore::GetAllServerBoundCertsTask::
210 GetAllServerBoundCertsTask(const GetCertListCallback
& callback
)
211 : callback_(callback
) {
214 DefaultServerBoundCertStore::GetAllServerBoundCertsTask::
215 ~GetAllServerBoundCertsTask() {
218 void DefaultServerBoundCertStore::GetAllServerBoundCertsTask::Run(
219 DefaultServerBoundCertStore
* store
) {
220 ServerBoundCertList cert_list
;
221 store
->SyncGetAllServerBoundCerts(&cert_list
);
223 InvokeCallback(base::Bind(callback_
, cert_list
));
226 // --------------------------------------------------------------------------
227 // DefaultServerBoundCertStore
230 const size_t DefaultServerBoundCertStore::kMaxCerts
= 3300;
232 DefaultServerBoundCertStore::DefaultServerBoundCertStore(
233 PersistentStore
* store
)
234 : initialized_(false),
237 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {}
239 bool DefaultServerBoundCertStore::GetServerBoundCert(
240 const std::string
& server_identifier
,
241 SSLClientCertType
* type
,
242 base::Time
* expiration_time
,
243 std::string
* private_key_result
,
244 std::string
* cert_result
,
245 const GetCertCallback
& callback
) {
246 DCHECK(CalledOnValidThread());
250 EnqueueTask(scoped_ptr
<Task
>(
251 new GetServerBoundCertTask(server_identifier
, callback
)));
255 ServerBoundCertMap::iterator it
= server_bound_certs_
.find(server_identifier
);
257 if (it
== server_bound_certs_
.end()) {
258 *type
= CLIENT_CERT_INVALID_TYPE
;
262 ServerBoundCert
* cert
= it
->second
;
263 *type
= cert
->type();
264 *expiration_time
= cert
->expiration_time();
265 *private_key_result
= cert
->private_key();
266 *cert_result
= cert
->cert();
271 void DefaultServerBoundCertStore::SetServerBoundCert(
272 const std::string
& server_identifier
,
273 SSLClientCertType type
,
274 base::Time creation_time
,
275 base::Time expiration_time
,
276 const std::string
& private_key
,
277 const std::string
& cert
) {
278 RunOrEnqueueTask(scoped_ptr
<Task
>(new SetServerBoundCertTask(
279 server_identifier
, type
, creation_time
, expiration_time
, private_key
,
283 void DefaultServerBoundCertStore::DeleteServerBoundCert(
284 const std::string
& server_identifier
,
285 const base::Closure
& callback
) {
286 RunOrEnqueueTask(scoped_ptr
<Task
>(
287 new DeleteServerBoundCertTask(server_identifier
, callback
)));
290 void DefaultServerBoundCertStore::DeleteAllCreatedBetween(
291 base::Time delete_begin
,
292 base::Time delete_end
,
293 const base::Closure
& callback
) {
294 RunOrEnqueueTask(scoped_ptr
<Task
>(
295 new DeleteAllCreatedBetweenTask(delete_begin
, delete_end
, callback
)));
298 void DefaultServerBoundCertStore::DeleteAll(
299 const base::Closure
& callback
) {
300 DeleteAllCreatedBetween(base::Time(), base::Time(), callback
);
303 void DefaultServerBoundCertStore::GetAllServerBoundCerts(
304 const GetCertListCallback
& callback
) {
305 RunOrEnqueueTask(scoped_ptr
<Task
>(new GetAllServerBoundCertsTask(callback
)));
308 int DefaultServerBoundCertStore::GetCertCount() {
309 DCHECK(CalledOnValidThread());
311 return server_bound_certs_
.size();
314 void DefaultServerBoundCertStore::SetForceKeepSessionState() {
315 DCHECK(CalledOnValidThread());
319 store_
->SetForceKeepSessionState();
322 DefaultServerBoundCertStore::~DefaultServerBoundCertStore() {
326 void DefaultServerBoundCertStore::DeleteAllInMemory() {
327 DCHECK(CalledOnValidThread());
329 for (ServerBoundCertMap::iterator it
= server_bound_certs_
.begin();
330 it
!= server_bound_certs_
.end(); ++it
) {
333 server_bound_certs_
.clear();
336 void DefaultServerBoundCertStore::InitStore() {
337 DCHECK(CalledOnValidThread());
338 DCHECK(store_
) << "Store must exist to initialize";
341 store_
->Load(base::Bind(&DefaultServerBoundCertStore::OnLoaded
,
342 weak_ptr_factory_
.GetWeakPtr()));
345 void DefaultServerBoundCertStore::OnLoaded(
346 scoped_ptr
<ScopedVector
<ServerBoundCert
> > certs
) {
347 DCHECK(CalledOnValidThread());
349 for (std::vector
<ServerBoundCert
*>::const_iterator it
= certs
->begin();
350 it
!= certs
->end(); ++it
) {
351 DCHECK(server_bound_certs_
.find((*it
)->server_identifier()) ==
352 server_bound_certs_
.end());
353 server_bound_certs_
[(*it
)->server_identifier()] = *it
;
359 base::TimeDelta wait_time
;
360 if (!waiting_tasks_
.empty())
361 wait_time
= base::TimeTicks::Now() - waiting_tasks_start_time_
;
362 DVLOG(1) << "Task delay " << wait_time
.InMilliseconds();
363 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.TaskMaxWaitTime",
365 base::TimeDelta::FromMilliseconds(1),
366 base::TimeDelta::FromMinutes(1),
368 UMA_HISTOGRAM_COUNTS_100("DomainBoundCerts.TaskWaitCount",
369 waiting_tasks_
.size());
372 for (ScopedVector
<Task
>::iterator i
= waiting_tasks_
.begin();
373 i
!= waiting_tasks_
.end(); ++i
)
375 waiting_tasks_
.clear();
378 void DefaultServerBoundCertStore::SyncSetServerBoundCert(
379 const std::string
& server_identifier
,
380 SSLClientCertType type
,
381 base::Time creation_time
,
382 base::Time expiration_time
,
383 const std::string
& private_key
,
384 const std::string
& cert
) {
385 DCHECK(CalledOnValidThread());
388 InternalDeleteServerBoundCert(server_identifier
);
389 InternalInsertServerBoundCert(
392 server_identifier
, type
, creation_time
, expiration_time
, private_key
,
396 void DefaultServerBoundCertStore::SyncDeleteServerBoundCert(
397 const std::string
& server_identifier
) {
398 DCHECK(CalledOnValidThread());
400 InternalDeleteServerBoundCert(server_identifier
);
403 void DefaultServerBoundCertStore::SyncDeleteAllCreatedBetween(
404 base::Time delete_begin
,
405 base::Time delete_end
) {
406 DCHECK(CalledOnValidThread());
408 for (ServerBoundCertMap::iterator it
= server_bound_certs_
.begin();
409 it
!= server_bound_certs_
.end();) {
410 ServerBoundCertMap::iterator cur
= it
;
412 ServerBoundCert
* cert
= cur
->second
;
413 if ((delete_begin
.is_null() || cert
->creation_time() >= delete_begin
) &&
414 (delete_end
.is_null() || cert
->creation_time() < delete_end
)) {
416 store_
->DeleteServerBoundCert(*cert
);
418 server_bound_certs_
.erase(cur
);
423 void DefaultServerBoundCertStore::SyncGetAllServerBoundCerts(
424 ServerBoundCertList
* cert_list
) {
425 DCHECK(CalledOnValidThread());
427 for (ServerBoundCertMap::iterator it
= server_bound_certs_
.begin();
428 it
!= server_bound_certs_
.end(); ++it
)
429 cert_list
->push_back(*it
->second
);
432 void DefaultServerBoundCertStore::EnqueueTask(scoped_ptr
<Task
> task
) {
433 DCHECK(CalledOnValidThread());
435 if (waiting_tasks_
.empty())
436 waiting_tasks_start_time_
= base::TimeTicks::Now();
437 waiting_tasks_
.push_back(task
.release());
440 void DefaultServerBoundCertStore::RunOrEnqueueTask(scoped_ptr
<Task
> task
) {
441 DCHECK(CalledOnValidThread());
445 EnqueueTask(task
.Pass());
452 void DefaultServerBoundCertStore::InternalDeleteServerBoundCert(
453 const std::string
& server_identifier
) {
454 DCHECK(CalledOnValidThread());
457 ServerBoundCertMap::iterator it
= server_bound_certs_
.find(server_identifier
);
458 if (it
== server_bound_certs_
.end())
459 return; // There is nothing to delete.
461 ServerBoundCert
* cert
= it
->second
;
463 store_
->DeleteServerBoundCert(*cert
);
464 server_bound_certs_
.erase(it
);
468 void DefaultServerBoundCertStore::InternalInsertServerBoundCert(
469 const std::string
& server_identifier
,
470 ServerBoundCert
* cert
) {
471 DCHECK(CalledOnValidThread());
475 store_
->AddServerBoundCert(*cert
);
476 server_bound_certs_
[server_identifier
] = cert
;
479 DefaultServerBoundCertStore::PersistentStore::PersistentStore() {}
481 DefaultServerBoundCertStore::PersistentStore::~PersistentStore() {}