OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/browser/media/webrtc_identity_store_backend.h" | 5 #include "content/browser/media/webrtc_identity_store_backend.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/memory/scoped_vector.h" |
| 10 #include "base/strings/string_util.h" |
9 #include "content/public/browser/browser_thread.h" | 11 #include "content/public/browser/browser_thread.h" |
10 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
11 #include "sql/error_delegate_util.h" | 13 #include "sql/error_delegate_util.h" |
12 #include "sql/statement.h" | 14 #include "sql/statement.h" |
13 #include "sql/transaction.h" | 15 #include "sql/transaction.h" |
14 #include "url/gurl.h" | 16 #include "url/gurl.h" |
15 #include "webkit/browser/quota/special_storage_policy.h" | 17 #include "webkit/browser/quota/special_storage_policy.h" |
16 | 18 |
17 namespace content { | 19 namespace content { |
18 | 20 |
19 static const char* kWebRTCIdentityStoreDBName = "webrtc_identity_store"; | 21 static const char* kWebRTCIdentityStoreDBName = "webrtc_identity_store"; |
20 | 22 |
21 static const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] = | 23 static const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] = |
22 FILE_PATH_LITERAL("WebRTCIdentityStore"); | 24 FILE_PATH_LITERAL("WebRTCIdentityStore"); |
23 | 25 |
24 // Initializes the identity table, returning true on success. | 26 // Initializes the identity table, returning true on success. |
25 static bool InitDB(sql::Connection* db) { | 27 static bool InitDB(sql::Connection* db) { |
26 if (db->DoesTableExist(kWebRTCIdentityStoreDBName)) { | 28 if (db->DoesTableExist(kWebRTCIdentityStoreDBName)) { |
27 if (db->DoesColumnExist(kWebRTCIdentityStoreDBName, "origin") && | 29 if (db->DoesColumnExist(kWebRTCIdentityStoreDBName, "origin") && |
28 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "identity_name") && | 30 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "identity_name") && |
29 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "common_name") && | 31 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "common_name") && |
30 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "certificate") && | 32 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "certificate") && |
31 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "private_key") && | 33 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "private_key") && |
32 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "creation_time")) | 34 db->DoesColumnExist(kWebRTCIdentityStoreDBName, "creation_time")) |
33 return true; | 35 return true; |
| 36 |
34 if (!db->Execute("DROP TABLE webrtc_identity_store")) | 37 if (!db->Execute("DROP TABLE webrtc_identity_store")) |
35 return false; | 38 return false; |
36 } | 39 } |
37 | 40 |
38 return db->Execute( | 41 return db->Execute( |
39 "CREATE TABLE webrtc_identity_store" | 42 "CREATE TABLE webrtc_identity_store" |
40 " (" | 43 " (" |
41 "origin TEXT NOT NULL," | 44 "origin TEXT NOT NULL," |
42 "identity_name TEXT NOT NULL," | 45 "identity_name TEXT NOT NULL," |
43 "common_name TEXT NOT NULL," | 46 "common_name TEXT NOT NULL," |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 : type(type), | 149 : type(type), |
147 origin(origin), | 150 origin(origin), |
148 identity_name(identity_name), | 151 identity_name(identity_name), |
149 identity(identity) {} | 152 identity(identity) {} |
150 | 153 |
151 OperationType type; | 154 OperationType type; |
152 GURL origin; | 155 GURL origin; |
153 std::string identity_name; | 156 std::string identity_name; |
154 Identity identity; | 157 Identity identity; |
155 }; | 158 }; |
156 typedef std::vector<PendingOperation*> PendingOperationList; | 159 typedef ScopedVector<PendingOperation> PendingOperationList; |
157 | 160 |
158 virtual ~SqlLiteStorage() {} | 161 virtual ~SqlLiteStorage() {} |
159 void OnDatabaseError(int error, sql::Statement* stmt); | 162 void OnDatabaseError(int error, sql::Statement* stmt); |
160 void BatchOperation(OperationType type, | 163 void BatchOperation(OperationType type, |
161 const GURL& origin, | 164 const GURL& origin, |
162 const std::string& identity_name, | 165 const std::string& identity_name, |
163 const Identity& identity); | 166 const Identity& identity); |
164 void Commit(); | 167 void Commit(); |
165 | 168 |
166 base::TimeDelta validity_period_; | 169 base::TimeDelta validity_period_; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 } | 339 } |
337 | 340 |
338 WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {} | 341 WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {} |
339 | 342 |
340 void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) { | 343 void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) { |
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
342 | 345 |
343 if (state_ != LOADING) | 346 if (state_ != LOADING) |
344 return; | 347 return; |
345 | 348 |
346 DVLOG(2) << "WebRTC identity store has loaded."; | 349 DVLOG(3) << "WebRTC identity store has loaded."; |
347 | 350 |
348 state_ = LOADED; | 351 state_ = LOADED; |
349 identities_.swap(*out_map); | 352 identities_.swap(*out_map); |
350 | 353 |
351 for (size_t i = 0; i < pending_find_requests_.size(); ++i) { | 354 for (size_t i = 0; i < pending_find_requests_.size(); ++i) { |
352 FindIdentity(pending_find_requests_[i]->origin, | 355 FindIdentity(pending_find_requests_[i]->origin, |
353 pending_find_requests_[i]->identity_name, | 356 pending_find_requests_[i]->identity_name, |
354 pending_find_requests_[i]->common_name, | 357 pending_find_requests_[i]->common_name, |
355 pending_find_requests_[i]->callback); | 358 pending_find_requests_[i]->callback); |
356 delete pending_find_requests_[i]; | 359 delete pending_find_requests_[i]; |
357 } | 360 } |
358 pending_find_requests_.clear(); | 361 pending_find_requests_.clear(); |
359 } | 362 } |
360 | 363 |
361 // | 364 // |
362 // Implementation of SqlLiteStorage. | 365 // Implementation of SqlLiteStorage. |
363 // | 366 // |
364 | 367 |
365 void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) { | 368 void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) { |
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
367 DCHECK(!db_.get()); | 370 DCHECK(!db_.get()); |
368 | 371 |
369 // Ensure the parent directory for storing certs is created before reading | 372 // Ensure the parent directory for storing certs is created before reading |
370 // from it. | 373 // from it. |
371 const base::FilePath dir = path_.DirName(); | 374 const base::FilePath dir = path_.DirName(); |
372 if (!base::PathExists(dir) && !base::CreateDirectory(dir)) { | 375 if (!base::PathExists(dir) && !base::CreateDirectory(dir)) { |
373 DLOG(ERROR) << "Unable to open DB file path."; | 376 DVLOG(2) << "Unable to open DB file path."; |
374 return; | 377 return; |
375 } | 378 } |
376 | 379 |
377 db_.reset(new sql::Connection()); | 380 db_.reset(new sql::Connection()); |
378 | 381 |
379 db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this)); | 382 db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this)); |
380 | 383 |
381 if (!db_->Open(path_)) { | 384 if (!db_->Open(path_)) { |
382 DLOG(ERROR) << "Unable to open DB."; | 385 DVLOG(2) << "Unable to open DB."; |
383 db_.reset(); | 386 db_.reset(); |
384 return; | 387 return; |
385 } | 388 } |
386 | 389 |
387 if (!InitDB(db_.get())) { | 390 if (!InitDB(db_.get())) { |
388 DLOG(ERROR) << "Unable to init DB."; | 391 DVLOG(2) << "Unable to init DB."; |
389 db_.reset(); | 392 db_.reset(); |
390 return; | 393 return; |
391 } | 394 } |
392 | 395 |
393 db_->Preload(); | 396 db_->Preload(); |
394 | 397 |
395 // Delete expired identities. | 398 // Delete expired identities. |
396 DeleteBetween(base::Time(), base::Time::Now() - validity_period_); | 399 DeleteBetween(base::Time(), base::Time::Now() - validity_period_); |
397 | 400 |
398 // Slurp all the identities into the out_map. | 401 // Slurp all the identities into the out_map. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 SQL_FROM_HERE, | 466 SQL_FROM_HERE, |
464 "DELETE FROM webrtc_identity_store" | 467 "DELETE FROM webrtc_identity_store" |
465 " WHERE creation_time >= ? AND creation_time <= ?")); | 468 " WHERE creation_time >= ? AND creation_time <= ?")); |
466 CHECK(del_stmt.is_valid()); | 469 CHECK(del_stmt.is_valid()); |
467 | 470 |
468 del_stmt.BindInt64(0, delete_begin.ToInternalValue()); | 471 del_stmt.BindInt64(0, delete_begin.ToInternalValue()); |
469 del_stmt.BindInt64(1, delete_end.ToInternalValue()); | 472 del_stmt.BindInt64(1, delete_end.ToInternalValue()); |
470 | 473 |
471 sql::Transaction transaction(db_.get()); | 474 sql::Transaction transaction(db_.get()); |
472 if (!transaction.Begin()) { | 475 if (!transaction.Begin()) { |
473 DLOG(ERROR) << "Failed to begin the transaction."; | 476 DVLOG(2) << "Failed to begin the transaction."; |
474 return; | 477 return; |
475 } | 478 } |
476 | 479 |
477 CHECK(del_stmt.Run()); | 480 if (!del_stmt.Run()) { |
478 transaction.Commit(); | 481 DVLOG(2) << "Failed to run the delete statement."; |
| 482 return; |
| 483 } |
| 484 |
| 485 if (!transaction.Commit()) |
| 486 DVLOG(2) << "Failed to commit the transaction."; |
479 } | 487 } |
480 | 488 |
481 void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError( | 489 void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError( |
482 int error, | 490 int error, |
483 sql::Statement* stmt) { | 491 sql::Statement* stmt) { |
484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
485 if (!sql::IsErrorCatastrophic(error)) | 493 |
486 return; | |
487 db_->RazeAndClose(); | 494 db_->RazeAndClose(); |
| 495 // It's not safe to reset |db_| here. |
488 } | 496 } |
489 | 497 |
490 void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation( | 498 void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation( |
491 OperationType type, | 499 OperationType type, |
492 const GURL& origin, | 500 const GURL& origin, |
493 const std::string& identity_name, | 501 const std::string& identity_name, |
494 const Identity& identity) { | 502 const Identity& identity) { |
495 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 503 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
496 // Commit every 30 seconds. | 504 // Commit every 30 seconds. |
497 static const base::TimeDelta kCommitInterval( | 505 static const base::TimeDelta kCommitInterval( |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 CHECK(add_stmt.is_valid()); | 543 CHECK(add_stmt.is_valid()); |
536 | 544 |
537 sql::Statement del_stmt(db_->GetCachedStatement( | 545 sql::Statement del_stmt(db_->GetCachedStatement( |
538 SQL_FROM_HERE, | 546 SQL_FROM_HERE, |
539 "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?")); | 547 "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?")); |
540 | 548 |
541 CHECK(del_stmt.is_valid()); | 549 CHECK(del_stmt.is_valid()); |
542 | 550 |
543 sql::Transaction transaction(db_.get()); | 551 sql::Transaction transaction(db_.get()); |
544 if (!transaction.Begin()) { | 552 if (!transaction.Begin()) { |
545 DLOG(ERROR) << "Failed to begin the transaction."; | 553 DVLOG(2) << "Failed to begin the transaction."; |
546 return; | 554 return; |
547 } | 555 } |
548 | 556 |
549 for (PendingOperationList::iterator it = pending_operations_.begin(); | 557 // Swaps |pending_operations_| into a temporary list to make sure |
550 it != pending_operations_.end(); | 558 // |pending_operations_| is always cleared in case of DB errors. |
| 559 PendingOperationList pending_operations_copy; |
| 560 pending_operations_.swap(pending_operations_copy); |
| 561 |
| 562 for (PendingOperationList::const_iterator it = |
| 563 pending_operations_copy.begin(); |
| 564 it != pending_operations_copy.end(); |
551 ++it) { | 565 ++it) { |
552 scoped_ptr<PendingOperation> po(*it); | 566 switch ((*it)->type) { |
553 switch (po->type) { | |
554 case ADD_IDENTITY: { | 567 case ADD_IDENTITY: { |
555 add_stmt.Reset(true); | 568 add_stmt.Reset(true); |
556 add_stmt.BindString(0, po->origin.spec()); | 569 add_stmt.BindString(0, (*it)->origin.spec()); |
557 add_stmt.BindString(1, po->identity_name); | 570 add_stmt.BindString(1, (*it)->identity_name); |
558 add_stmt.BindString(2, po->identity.common_name); | 571 add_stmt.BindString(2, (*it)->identity.common_name); |
559 const std::string& cert = po->identity.certificate; | 572 const std::string& cert = (*it)->identity.certificate; |
560 add_stmt.BindBlob(3, cert.data(), cert.size()); | 573 add_stmt.BindBlob(3, cert.data(), cert.size()); |
561 const std::string& private_key = po->identity.private_key; | 574 const std::string& private_key = (*it)->identity.private_key; |
562 add_stmt.BindBlob(4, private_key.data(), private_key.size()); | 575 add_stmt.BindBlob(4, private_key.data(), private_key.size()); |
563 add_stmt.BindInt64(5, po->identity.creation_time); | 576 add_stmt.BindInt64(5, (*it)->identity.creation_time); |
564 CHECK(add_stmt.Run()); | 577 if (!add_stmt.Run()) { |
| 578 DVLOG(2) << "Failed to add the identity to DB."; |
| 579 return; |
| 580 } |
565 break; | 581 break; |
566 } | 582 } |
567 case DELETE_IDENTITY: | 583 case DELETE_IDENTITY: |
568 del_stmt.Reset(true); | 584 del_stmt.Reset(true); |
569 del_stmt.BindString(0, po->origin.spec()); | 585 del_stmt.BindString(0, (*it)->origin.spec()); |
570 del_stmt.BindString(1, po->identity_name); | 586 del_stmt.BindString(1, (*it)->identity_name); |
571 CHECK(del_stmt.Run()); | 587 if (!del_stmt.Run()) { |
| 588 DVLOG(2) << "Failed to delete the identity from DB."; |
| 589 return; |
| 590 } |
572 break; | 591 break; |
573 | 592 |
574 default: | 593 default: |
575 NOTREACHED(); | 594 NOTREACHED(); |
576 break; | 595 break; |
577 } | 596 } |
578 } | 597 } |
579 transaction.Commit(); | 598 |
580 pending_operations_.clear(); | 599 if (!transaction.Commit()) |
| 600 DVLOG(2) << "Failed to commit the transaction."; |
581 } | 601 } |
582 | 602 |
583 } // namespace content | 603 } // namespace content |
OLD | NEW |