OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/net/sqlite_server_bound_cert_store.h" | 5 #include "chrome/browser/net/sqlite_server_bound_cert_store.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 : public base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend> { | 34 : public base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend> { |
35 public: | 35 public: |
36 Backend(const FilePath& path, ClearOnExitPolicy* clear_on_exit_policy) | 36 Backend(const FilePath& path, ClearOnExitPolicy* clear_on_exit_policy) |
37 : path_(path), | 37 : path_(path), |
38 db_(NULL), | 38 db_(NULL), |
39 num_pending_(0), | 39 num_pending_(0), |
40 force_keep_session_state_(false), | 40 force_keep_session_state_(false), |
41 clear_on_exit_policy_(clear_on_exit_policy) { | 41 clear_on_exit_policy_(clear_on_exit_policy) { |
42 } | 42 } |
43 | 43 |
44 // Creates or load the SQLite database. | 44 // Creates or loads the SQLite database. |
45 bool Load( | 45 void Load(const LoadedCallback& loaded_callback); |
46 std::vector<net::DefaultServerBoundCertStore::ServerBoundCert*>* certs); | |
47 | 46 |
48 // Batch a server bound cert addition. | 47 // Batch a server bound cert addition. |
49 void AddServerBoundCert( | 48 void AddServerBoundCert( |
50 const net::DefaultServerBoundCertStore::ServerBoundCert& cert); | 49 const net::DefaultServerBoundCertStore::ServerBoundCert& cert); |
51 | 50 |
52 // Batch a server bound cert deletion. | 51 // Batch a server bound cert deletion. |
53 void DeleteServerBoundCert( | 52 void DeleteServerBoundCert( |
54 const net::DefaultServerBoundCertStore::ServerBoundCert& cert); | 53 const net::DefaultServerBoundCertStore::ServerBoundCert& cert); |
55 | 54 |
56 // Commit pending operations as soon as possible. | 55 // Commit pending operations as soon as possible. |
57 void Flush(const base::Closure& completion_task); | 56 void Flush(const base::Closure& completion_task); |
58 | 57 |
59 // Commit any pending operations and close the database. This must be called | 58 // Commit any pending operations and close the database. This must be called |
60 // before the object is destructed. | 59 // before the object is destructed. |
61 void Close(); | 60 void Close(); |
62 | 61 |
63 void SetForceKeepSessionState(); | 62 void SetForceKeepSessionState(); |
64 | 63 |
65 private: | 64 private: |
| 65 void LoadOnDBThreadAndNotify(const LoadedCallback& loaded_callback); |
| 66 void LoadOnDBThread( |
| 67 std::vector<net::DefaultServerBoundCertStore::ServerBoundCert*>* certs); |
| 68 |
66 friend class base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend>; | 69 friend class base::RefCountedThreadSafe<SQLiteServerBoundCertStore::Backend>; |
67 | 70 |
68 // You should call Close() before destructing this object. | 71 // You should call Close() before destructing this object. |
69 ~Backend() { | 72 ~Backend() { |
70 DCHECK(!db_.get()) << "Close should have already been called."; | 73 DCHECK(!db_.get()) << "Close should have already been called."; |
71 DCHECK(num_pending_ == 0 && pending_.empty()); | 74 DCHECK(num_pending_ == 0 && pending_.empty()); |
72 } | 75 } |
73 | 76 |
74 // Database upgrade statements. | 77 // Database upgrade statements. |
75 bool EnsureDatabaseVersion(); | 78 bool EnsureDatabaseVersion(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 "expiration_time INTEGER," | 151 "expiration_time INTEGER," |
149 "creation_time INTEGER)")) | 152 "creation_time INTEGER)")) |
150 return false; | 153 return false; |
151 } | 154 } |
152 | 155 |
153 return true; | 156 return true; |
154 } | 157 } |
155 | 158 |
156 } // namespace | 159 } // namespace |
157 | 160 |
158 bool SQLiteServerBoundCertStore::Backend::Load( | 161 void SQLiteServerBoundCertStore::Backend::Load( |
159 std::vector<net::DefaultServerBoundCertStore::ServerBoundCert*>* certs) { | 162 const LoadedCallback& loaded_callback) { |
160 // This function should be called only once per instance. | 163 // This function should be called only once per instance. |
161 DCHECK(!db_.get()); | 164 DCHECK(!db_.get()); |
162 | 165 |
163 // TODO(paivanof@gmail.com): We do a lot of disk access in this function, | 166 BrowserThread::PostTask( |
164 // thus we do an exception to allow IO on the UI thread. This code will be | 167 BrowserThread::DB, FROM_HERE, |
165 // moved to the DB thread as part of http://crbug.com/89665. | 168 base::Bind(&Backend::LoadOnDBThreadAndNotify, this, loaded_callback)); |
166 base::ThreadRestrictions::ScopedAllowIO allow_io; | 169 } |
| 170 |
| 171 void SQLiteServerBoundCertStore::Backend::LoadOnDBThreadAndNotify( |
| 172 const LoadedCallback& loaded_callback) { |
| 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 174 scoped_ptr<ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert> > |
| 175 certs(new ScopedVector<net::DefaultServerBoundCertStore::ServerBoundCert>( |
| 176 )); |
| 177 |
| 178 LoadOnDBThread(&certs->get()); |
| 179 |
| 180 BrowserThread::PostTask( |
| 181 BrowserThread::IO, FROM_HERE, |
| 182 base::Bind(loaded_callback, base::Passed(&certs))); |
| 183 } |
| 184 |
| 185 void SQLiteServerBoundCertStore::Backend::LoadOnDBThread( |
| 186 std::vector<net::DefaultServerBoundCertStore::ServerBoundCert*>* certs) { |
| 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 188 |
| 189 // This method should be called only once per instance. |
| 190 DCHECK(!db_.get()); |
167 | 191 |
168 base::TimeTicks start = base::TimeTicks::Now(); | 192 base::TimeTicks start = base::TimeTicks::Now(); |
169 | 193 |
170 // Ensure the parent directory for storing certs is created before reading | 194 // Ensure the parent directory for storing certs is created before reading |
171 // from it. | 195 // from it. |
172 const FilePath dir = path_.DirName(); | 196 const FilePath dir = path_.DirName(); |
173 if (!file_util::PathExists(dir) && !file_util::CreateDirectory(dir)) | 197 if (!file_util::PathExists(dir) && !file_util::CreateDirectory(dir)) |
174 return false; | 198 return; |
175 | 199 |
176 int64 db_size = 0; | 200 int64 db_size = 0; |
177 if (file_util::GetFileSize(path_, &db_size)) | 201 if (file_util::GetFileSize(path_, &db_size)) |
178 UMA_HISTOGRAM_COUNTS("DomainBoundCerts.DBSizeInKB", db_size / 1024 ); | 202 UMA_HISTOGRAM_COUNTS("DomainBoundCerts.DBSizeInKB", db_size / 1024 ); |
179 | 203 |
180 db_.reset(new sql::Connection); | 204 db_.reset(new sql::Connection); |
181 if (!db_->Open(path_)) { | 205 if (!db_->Open(path_)) { |
182 NOTREACHED() << "Unable to open cert DB."; | 206 NOTREACHED() << "Unable to open cert DB."; |
183 db_.reset(); | 207 db_.reset(); |
184 return false; | 208 return; |
185 } | 209 } |
186 | 210 |
187 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { | 211 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { |
188 NOTREACHED() << "Unable to open cert DB."; | 212 NOTREACHED() << "Unable to open cert DB."; |
189 db_.reset(); | 213 db_.reset(); |
190 return false; | 214 return; |
191 } | 215 } |
192 | 216 |
193 db_->Preload(); | 217 db_->Preload(); |
194 | 218 |
195 // Slurp all the certs into the out-vector. | 219 // Slurp all the certs into the out-vector. |
196 sql::Statement smt(db_->GetUniqueStatement( | 220 sql::Statement smt(db_->GetUniqueStatement( |
197 "SELECT origin, private_key, cert, cert_type, expiration_time, " | 221 "SELECT origin, private_key, cert, cert_type, expiration_time, " |
198 "creation_time FROM origin_bound_certs")); | 222 "creation_time FROM origin_bound_certs")); |
199 if (!smt.is_valid()) { | 223 if (!smt.is_valid()) { |
200 db_.reset(); | 224 db_.reset(); |
201 return false; | 225 return; |
202 } | 226 } |
203 | 227 |
204 while (smt.Step()) { | 228 while (smt.Step()) { |
205 std::string private_key_from_db, cert_from_db; | 229 std::string private_key_from_db, cert_from_db; |
206 smt.ColumnBlobAsString(1, &private_key_from_db); | 230 smt.ColumnBlobAsString(1, &private_key_from_db); |
207 smt.ColumnBlobAsString(2, &cert_from_db); | 231 smt.ColumnBlobAsString(2, &cert_from_db); |
208 scoped_ptr<net::DefaultServerBoundCertStore::ServerBoundCert> cert( | 232 scoped_ptr<net::DefaultServerBoundCertStore::ServerBoundCert> cert( |
209 new net::DefaultServerBoundCertStore::ServerBoundCert( | 233 new net::DefaultServerBoundCertStore::ServerBoundCert( |
210 smt.ColumnString(0), // origin | 234 smt.ColumnString(0), // origin |
211 static_cast<net::SSLClientCertType>(smt.ColumnInt(3)), | 235 static_cast<net::SSLClientCertType>(smt.ColumnInt(3)), |
212 base::Time::FromInternalValue(smt.ColumnInt64(5)), | 236 base::Time::FromInternalValue(smt.ColumnInt64(5)), |
213 base::Time::FromInternalValue(smt.ColumnInt64(4)), | 237 base::Time::FromInternalValue(smt.ColumnInt64(4)), |
214 private_key_from_db, | 238 private_key_from_db, |
215 cert_from_db)); | 239 cert_from_db)); |
216 cert_origins_.insert(cert->server_identifier()); | 240 cert_origins_.insert(cert->server_identifier()); |
217 certs->push_back(cert.release()); | 241 certs->push_back(cert.release()); |
218 } | 242 } |
219 | 243 |
220 UMA_HISTOGRAM_COUNTS_10000("DomainBoundCerts.DBLoadedCount", certs->size()); | 244 UMA_HISTOGRAM_COUNTS_10000("DomainBoundCerts.DBLoadedCount", certs->size()); |
| 245 base::TimeDelta load_time = base::TimeTicks::Now() - start; |
221 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.DBLoadTime", | 246 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.DBLoadTime", |
222 base::TimeTicks::Now() - start, | 247 load_time, |
223 base::TimeDelta::FromMilliseconds(1), | 248 base::TimeDelta::FromMilliseconds(1), |
224 base::TimeDelta::FromMinutes(1), | 249 base::TimeDelta::FromMinutes(1), |
225 50); | 250 50); |
226 return true; | 251 DVLOG(1) << "loaded " << certs->size() << " in " << load_time.InMilliseconds() |
| 252 << " ms"; |
227 } | 253 } |
228 | 254 |
229 bool SQLiteServerBoundCertStore::Backend::EnsureDatabaseVersion() { | 255 bool SQLiteServerBoundCertStore::Backend::EnsureDatabaseVersion() { |
230 // Version check. | 256 // Version check. |
231 if (!meta_table_.Init( | 257 if (!meta_table_.Init( |
232 db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) { | 258 db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) { |
233 return false; | 259 return false; |
234 } | 260 } |
235 | 261 |
236 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { | 262 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 base::AutoLock locked(lock_); | 563 base::AutoLock locked(lock_); |
538 force_keep_session_state_ = true; | 564 force_keep_session_state_ = true; |
539 } | 565 } |
540 | 566 |
541 SQLiteServerBoundCertStore::SQLiteServerBoundCertStore( | 567 SQLiteServerBoundCertStore::SQLiteServerBoundCertStore( |
542 const FilePath& path, | 568 const FilePath& path, |
543 ClearOnExitPolicy* clear_on_exit_policy) | 569 ClearOnExitPolicy* clear_on_exit_policy) |
544 : backend_(new Backend(path, clear_on_exit_policy)) { | 570 : backend_(new Backend(path, clear_on_exit_policy)) { |
545 } | 571 } |
546 | 572 |
547 bool SQLiteServerBoundCertStore::Load( | 573 void SQLiteServerBoundCertStore::Load( |
548 std::vector<net::DefaultServerBoundCertStore::ServerBoundCert*>* certs) { | 574 const LoadedCallback& loaded_callback) { |
549 return backend_->Load(certs); | 575 backend_->Load(loaded_callback); |
550 } | 576 } |
551 | 577 |
552 void SQLiteServerBoundCertStore::AddServerBoundCert( | 578 void SQLiteServerBoundCertStore::AddServerBoundCert( |
553 const net::DefaultServerBoundCertStore::ServerBoundCert& cert) { | 579 const net::DefaultServerBoundCertStore::ServerBoundCert& cert) { |
554 backend_->AddServerBoundCert(cert); | 580 backend_->AddServerBoundCert(cert); |
555 } | 581 } |
556 | 582 |
557 void SQLiteServerBoundCertStore::DeleteServerBoundCert( | 583 void SQLiteServerBoundCertStore::DeleteServerBoundCert( |
558 const net::DefaultServerBoundCertStore::ServerBoundCert& cert) { | 584 const net::DefaultServerBoundCertStore::ServerBoundCert& cert) { |
559 backend_->DeleteServerBoundCert(cert); | 585 backend_->DeleteServerBoundCert(cert); |
560 } | 586 } |
561 | 587 |
562 void SQLiteServerBoundCertStore::SetForceKeepSessionState() { | 588 void SQLiteServerBoundCertStore::SetForceKeepSessionState() { |
563 backend_->SetForceKeepSessionState(); | 589 backend_->SetForceKeepSessionState(); |
564 } | 590 } |
565 | 591 |
566 void SQLiteServerBoundCertStore::Flush(const base::Closure& completion_task) { | 592 void SQLiteServerBoundCertStore::Flush(const base::Closure& completion_task) { |
567 backend_->Flush(completion_task); | 593 backend_->Flush(completion_task); |
568 } | 594 } |
569 | 595 |
570 SQLiteServerBoundCertStore::~SQLiteServerBoundCertStore() { | 596 SQLiteServerBoundCertStore::~SQLiteServerBoundCertStore() { |
571 backend_->Close(); | 597 backend_->Close(); |
572 // We release our reference to the Backend, though it will probably still have | 598 // We release our reference to the Backend, though it will probably still have |
573 // a reference if the background thread has not run Close() yet. | 599 // a reference if the background thread has not run Close() yet. |
574 } | 600 } |
OLD | NEW |