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