| 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 |