| 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/files/file_path.h" | 7 #include "base/files/file_path.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/memory/scoped_vector.h" | 9 #include "base/memory/scoped_vector.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 void Close(); | 122 void Close(); |
| 123 void AddIdentity(const GURL& origin, | 123 void AddIdentity(const GURL& origin, |
| 124 const std::string& identity_name, | 124 const std::string& identity_name, |
| 125 const Identity& identity); | 125 const Identity& identity); |
| 126 void DeleteIdentity(const GURL& origin, | 126 void DeleteIdentity(const GURL& origin, |
| 127 const std::string& identity_name, | 127 const std::string& identity_name, |
| 128 const Identity& identity); | 128 const Identity& identity); |
| 129 void DeleteBetween(base::Time delete_begin, base::Time delete_end); | 129 void DeleteBetween(base::Time delete_begin, base::Time delete_end); |
| 130 | 130 |
| 131 void SetValidityPeriodForTesting(base::TimeDelta validity_period) { | 131 void SetValidityPeriodForTesting(base::TimeDelta validity_period) { |
| 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 132 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 133 DCHECK(!db_.get()); | 133 DCHECK(!db_.get()); |
| 134 validity_period_ = validity_period; | 134 validity_period_ = validity_period; |
| 135 } | 135 } |
| 136 | 136 |
| 137 private: | 137 private: |
| 138 friend class base::RefCountedThreadSafe<SqlLiteStorage>; | 138 friend class base::RefCountedThreadSafe<SqlLiteStorage>; |
| 139 | 139 |
| 140 enum OperationType { | 140 enum OperationType { |
| 141 ADD_IDENTITY, | 141 ADD_IDENTITY, |
| 142 DELETE_IDENTITY | 142 DELETE_IDENTITY |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 : validity_period_(validity_period), | 184 : validity_period_(validity_period), |
| 185 state_(NOT_STARTED), | 185 state_(NOT_STARTED), |
| 186 sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) { | 186 sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) { |
| 187 } | 187 } |
| 188 | 188 |
| 189 bool WebRTCIdentityStoreBackend::FindIdentity( | 189 bool WebRTCIdentityStoreBackend::FindIdentity( |
| 190 const GURL& origin, | 190 const GURL& origin, |
| 191 const std::string& identity_name, | 191 const std::string& identity_name, |
| 192 const std::string& common_name, | 192 const std::string& common_name, |
| 193 const FindIdentityCallback& callback) { | 193 const FindIdentityCallback& callback) { |
| 194 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 194 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 195 if (state_ == CLOSED) | 195 if (state_ == CLOSED) |
| 196 return false; | 196 return false; |
| 197 | 197 |
| 198 if (state_ != LOADED) { | 198 if (state_ != LOADED) { |
| 199 // Queues the request to wait for the DB to load. | 199 // Queues the request to wait for the DB to load. |
| 200 pending_find_requests_.push_back( | 200 pending_find_requests_.push_back( |
| 201 new PendingFindRequest(origin, identity_name, common_name, callback)); | 201 new PendingFindRequest(origin, identity_name, common_name, callback)); |
| 202 if (state_ == LOADING) | 202 if (state_ == LOADING) |
| 203 return true; | 203 return true; |
| 204 | 204 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 BrowserThread::IO, | 245 BrowserThread::IO, |
| 246 FROM_HERE, | 246 FROM_HERE, |
| 247 base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", "")); | 247 base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", "")); |
| 248 } | 248 } |
| 249 | 249 |
| 250 void WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin, | 250 void WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin, |
| 251 const std::string& identity_name, | 251 const std::string& identity_name, |
| 252 const std::string& common_name, | 252 const std::string& common_name, |
| 253 const std::string& certificate, | 253 const std::string& certificate, |
| 254 const std::string& private_key) { | 254 const std::string& private_key) { |
| 255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 255 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 256 if (state_ == CLOSED) | 256 if (state_ == CLOSED) |
| 257 return; | 257 return; |
| 258 | 258 |
| 259 // If there is an existing identity for the same origin and identity_name, | 259 // If there is an existing identity for the same origin and identity_name, |
| 260 // delete it. | 260 // delete it. |
| 261 IdentityKey key(origin, identity_name); | 261 IdentityKey key(origin, identity_name); |
| 262 Identity identity(common_name, certificate, private_key); | 262 Identity identity(common_name, certificate, private_key); |
| 263 | 263 |
| 264 if (identities_.find(key) != identities_.end()) { | 264 if (identities_.find(key) != identities_.end()) { |
| 265 if (!BrowserThread::PostTask(BrowserThread::DB, | 265 if (!BrowserThread::PostTask(BrowserThread::DB, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 state_ = CLOSED; | 297 state_ = CLOSED; |
| 298 BrowserThread::PostTask( | 298 BrowserThread::PostTask( |
| 299 BrowserThread::DB, | 299 BrowserThread::DB, |
| 300 FROM_HERE, | 300 FROM_HERE, |
| 301 base::Bind(&SqlLiteStorage::Close, sql_lite_storage_)); | 301 base::Bind(&SqlLiteStorage::Close, sql_lite_storage_)); |
| 302 } | 302 } |
| 303 | 303 |
| 304 void WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin, | 304 void WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin, |
| 305 base::Time delete_end, | 305 base::Time delete_end, |
| 306 const base::Closure& callback) { | 306 const base::Closure& callback) { |
| 307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 307 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 308 if (state_ == CLOSED) | 308 if (state_ == CLOSED) |
| 309 return; | 309 return; |
| 310 | 310 |
| 311 // Delete the in-memory cache. | 311 // Delete the in-memory cache. |
| 312 IdentityMap::iterator it = identities_.begin(); | 312 IdentityMap::iterator it = identities_.begin(); |
| 313 while (it != identities_.end()) { | 313 while (it != identities_.end()) { |
| 314 if (it->second.creation_time >= delete_begin.ToInternalValue() && | 314 if (it->second.creation_time >= delete_begin.ToInternalValue() && |
| 315 it->second.creation_time <= delete_end.ToInternalValue()) { | 315 it->second.creation_time <= delete_end.ToInternalValue()) { |
| 316 identities_.erase(it++); | 316 identities_.erase(it++); |
| 317 } else { | 317 } else { |
| 318 ++it; | 318 ++it; |
| 319 } | 319 } |
| 320 } | 320 } |
| 321 BrowserThread::PostTaskAndReply(BrowserThread::DB, | 321 BrowserThread::PostTaskAndReply(BrowserThread::DB, |
| 322 FROM_HERE, | 322 FROM_HERE, |
| 323 base::Bind(&SqlLiteStorage::DeleteBetween, | 323 base::Bind(&SqlLiteStorage::DeleteBetween, |
| 324 sql_lite_storage_, | 324 sql_lite_storage_, |
| 325 delete_begin, | 325 delete_begin, |
| 326 delete_end), | 326 delete_end), |
| 327 callback); | 327 callback); |
| 328 } | 328 } |
| 329 | 329 |
| 330 void WebRTCIdentityStoreBackend::SetValidityPeriodForTesting( | 330 void WebRTCIdentityStoreBackend::SetValidityPeriodForTesting( |
| 331 base::TimeDelta validity_period) { | 331 base::TimeDelta validity_period) { |
| 332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 332 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 333 validity_period_ = validity_period; | 333 validity_period_ = validity_period; |
| 334 BrowserThread::PostTask( | 334 BrowserThread::PostTask( |
| 335 BrowserThread::DB, | 335 BrowserThread::DB, |
| 336 FROM_HERE, | 336 FROM_HERE, |
| 337 base::Bind(&SqlLiteStorage::SetValidityPeriodForTesting, | 337 base::Bind(&SqlLiteStorage::SetValidityPeriodForTesting, |
| 338 sql_lite_storage_, | 338 sql_lite_storage_, |
| 339 validity_period)); | 339 validity_period)); |
| 340 } | 340 } |
| 341 | 341 |
| 342 WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {} | 342 WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {} |
| 343 | 343 |
| 344 void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) { | 344 void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) { |
| 345 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 345 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 346 | 346 |
| 347 if (state_ != LOADING) | 347 if (state_ != LOADING) |
| 348 return; | 348 return; |
| 349 | 349 |
| 350 DVLOG(3) << "WebRTC identity store has loaded."; | 350 DVLOG(3) << "WebRTC identity store has loaded."; |
| 351 | 351 |
| 352 state_ = LOADED; | 352 state_ = LOADED; |
| 353 identities_.swap(*out_map); | 353 identities_.swap(*out_map); |
| 354 | 354 |
| 355 for (size_t i = 0; i < pending_find_requests_.size(); ++i) { | 355 for (size_t i = 0; i < pending_find_requests_.size(); ++i) { |
| 356 FindIdentity(pending_find_requests_[i]->origin, | 356 FindIdentity(pending_find_requests_[i]->origin, |
| 357 pending_find_requests_[i]->identity_name, | 357 pending_find_requests_[i]->identity_name, |
| 358 pending_find_requests_[i]->common_name, | 358 pending_find_requests_[i]->common_name, |
| 359 pending_find_requests_[i]->callback); | 359 pending_find_requests_[i]->callback); |
| 360 delete pending_find_requests_[i]; | 360 delete pending_find_requests_[i]; |
| 361 } | 361 } |
| 362 pending_find_requests_.clear(); | 362 pending_find_requests_.clear(); |
| 363 } | 363 } |
| 364 | 364 |
| 365 // | 365 // |
| 366 // Implementation of SqlLiteStorage. | 366 // Implementation of SqlLiteStorage. |
| 367 // | 367 // |
| 368 | 368 |
| 369 void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) { | 369 void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) { |
| 370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 370 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 371 DCHECK(!db_.get()); | 371 DCHECK(!db_.get()); |
| 372 | 372 |
| 373 // Ensure the parent directory for storing certs is created before reading | 373 // Ensure the parent directory for storing certs is created before reading |
| 374 // from it. | 374 // from it. |
| 375 const base::FilePath dir = path_.DirName(); | 375 const base::FilePath dir = path_.DirName(); |
| 376 if (!base::PathExists(dir) && !base::CreateDirectory(dir)) { | 376 if (!base::PathExists(dir) && !base::CreateDirectory(dir)) { |
| 377 DVLOG(2) << "Unable to open DB file path."; | 377 DVLOG(2) << "Unable to open DB file path."; |
| 378 return; | 378 return; |
| 379 } | 379 } |
| 380 | 380 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 stmt.ColumnBlobAsString(4, &private_key); | 414 stmt.ColumnBlobAsString(4, &private_key); |
| 415 int64 creation_time = stmt.ColumnInt64(5); | 415 int64 creation_time = stmt.ColumnInt64(5); |
| 416 std::pair<IdentityMap::iterator, bool> result = | 416 std::pair<IdentityMap::iterator, bool> result = |
| 417 out_map->insert(std::pair<IdentityKey, Identity>( | 417 out_map->insert(std::pair<IdentityKey, Identity>( |
| 418 key, Identity(common_name, cert, private_key, creation_time))); | 418 key, Identity(common_name, cert, private_key, creation_time))); |
| 419 DCHECK(result.second); | 419 DCHECK(result.second); |
| 420 } | 420 } |
| 421 } | 421 } |
| 422 | 422 |
| 423 void WebRTCIdentityStoreBackend::SqlLiteStorage::Close() { | 423 void WebRTCIdentityStoreBackend::SqlLiteStorage::Close() { |
| 424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 424 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 425 Commit(); | 425 Commit(); |
| 426 db_.reset(); | 426 db_.reset(); |
| 427 } | 427 } |
| 428 | 428 |
| 429 void WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity( | 429 void WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity( |
| 430 const GURL& origin, | 430 const GURL& origin, |
| 431 const std::string& identity_name, | 431 const std::string& identity_name, |
| 432 const Identity& identity) { | 432 const Identity& identity) { |
| 433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 433 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 434 if (!db_.get()) | 434 if (!db_.get()) |
| 435 return; | 435 return; |
| 436 | 436 |
| 437 // Do not add for session only origins. | 437 // Do not add for session only origins. |
| 438 if (special_storage_policy_.get() && | 438 if (special_storage_policy_.get() && |
| 439 !special_storage_policy_->IsStorageProtected(origin) && | 439 !special_storage_policy_->IsStorageProtected(origin) && |
| 440 special_storage_policy_->IsStorageSessionOnly(origin)) { | 440 special_storage_policy_->IsStorageSessionOnly(origin)) { |
| 441 return; | 441 return; |
| 442 } | 442 } |
| 443 BatchOperation(ADD_IDENTITY, origin, identity_name, identity); | 443 BatchOperation(ADD_IDENTITY, origin, identity_name, identity); |
| 444 } | 444 } |
| 445 | 445 |
| 446 void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity( | 446 void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity( |
| 447 const GURL& origin, | 447 const GURL& origin, |
| 448 const std::string& identity_name, | 448 const std::string& identity_name, |
| 449 const Identity& identity) { | 449 const Identity& identity) { |
| 450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 450 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 451 if (!db_.get()) | 451 if (!db_.get()) |
| 452 return; | 452 return; |
| 453 BatchOperation(DELETE_IDENTITY, origin, identity_name, identity); | 453 BatchOperation(DELETE_IDENTITY, origin, identity_name, identity); |
| 454 } | 454 } |
| 455 | 455 |
| 456 void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween( | 456 void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween( |
| 457 base::Time delete_begin, | 457 base::Time delete_begin, |
| 458 base::Time delete_end) { | 458 base::Time delete_end) { |
| 459 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 459 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 460 if (!db_.get()) | 460 if (!db_.get()) |
| 461 return; | 461 return; |
| 462 | 462 |
| 463 // Commit pending operations first. | 463 // Commit pending operations first. |
| 464 Commit(); | 464 Commit(); |
| 465 | 465 |
| 466 sql::Statement del_stmt(db_->GetCachedStatement( | 466 sql::Statement del_stmt(db_->GetCachedStatement( |
| 467 SQL_FROM_HERE, | 467 SQL_FROM_HERE, |
| 468 "DELETE FROM webrtc_identity_store" | 468 "DELETE FROM webrtc_identity_store" |
| 469 " WHERE creation_time >= ? AND creation_time <= ?")); | 469 " WHERE creation_time >= ? AND creation_time <= ?")); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 483 return; | 483 return; |
| 484 } | 484 } |
| 485 | 485 |
| 486 if (!transaction.Commit()) | 486 if (!transaction.Commit()) |
| 487 DVLOG(2) << "Failed to commit the transaction."; | 487 DVLOG(2) << "Failed to commit the transaction."; |
| 488 } | 488 } |
| 489 | 489 |
| 490 void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError( | 490 void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError( |
| 491 int error, | 491 int error, |
| 492 sql::Statement* stmt) { | 492 sql::Statement* stmt) { |
| 493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 493 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 494 | 494 |
| 495 db_->RazeAndClose(); | 495 db_->RazeAndClose(); |
| 496 // It's not safe to reset |db_| here. | 496 // It's not safe to reset |db_| here. |
| 497 } | 497 } |
| 498 | 498 |
| 499 void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation( | 499 void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation( |
| 500 OperationType type, | 500 OperationType type, |
| 501 const GURL& origin, | 501 const GURL& origin, |
| 502 const std::string& identity_name, | 502 const std::string& identity_name, |
| 503 const Identity& identity) { | 503 const Identity& identity) { |
| 504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 504 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 505 // Commit every 30 seconds. | 505 // Commit every 30 seconds. |
| 506 static const base::TimeDelta kCommitInterval( | 506 static const base::TimeDelta kCommitInterval( |
| 507 base::TimeDelta::FromSeconds(30)); | 507 base::TimeDelta::FromSeconds(30)); |
| 508 // Commit right away if we have more than 512 outstanding operations. | 508 // Commit right away if we have more than 512 outstanding operations. |
| 509 static const size_t kCommitAfterBatchSize = 512; | 509 static const size_t kCommitAfterBatchSize = 512; |
| 510 | 510 |
| 511 // We do a full copy of the cert here, and hopefully just here. | 511 // We do a full copy of the cert here, and hopefully just here. |
| 512 scoped_ptr<PendingOperation> operation( | 512 scoped_ptr<PendingOperation> operation( |
| 513 new PendingOperation(type, origin, identity_name, identity)); | 513 new PendingOperation(type, origin, identity_name, identity)); |
| 514 | 514 |
| 515 pending_operations_.push_back(operation.release()); | 515 pending_operations_.push_back(operation.release()); |
| 516 | 516 |
| 517 if (pending_operations_.size() == 1) { | 517 if (pending_operations_.size() == 1) { |
| 518 // We've gotten our first entry for this batch, fire off the timer. | 518 // We've gotten our first entry for this batch, fire off the timer. |
| 519 BrowserThread::PostDelayedTask(BrowserThread::DB, | 519 BrowserThread::PostDelayedTask(BrowserThread::DB, |
| 520 FROM_HERE, | 520 FROM_HERE, |
| 521 base::Bind(&SqlLiteStorage::Commit, this), | 521 base::Bind(&SqlLiteStorage::Commit, this), |
| 522 kCommitInterval); | 522 kCommitInterval); |
| 523 } else if (pending_operations_.size() >= kCommitAfterBatchSize) { | 523 } else if (pending_operations_.size() >= kCommitAfterBatchSize) { |
| 524 // We've reached a big enough batch, fire off a commit now. | 524 // We've reached a big enough batch, fire off a commit now. |
| 525 BrowserThread::PostTask(BrowserThread::DB, | 525 BrowserThread::PostTask(BrowserThread::DB, |
| 526 FROM_HERE, | 526 FROM_HERE, |
| 527 base::Bind(&SqlLiteStorage::Commit, this)); | 527 base::Bind(&SqlLiteStorage::Commit, this)); |
| 528 } | 528 } |
| 529 } | 529 } |
| 530 | 530 |
| 531 void WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() { | 531 void WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() { |
| 532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 532 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 533 // Maybe an old timer fired or we are already Close()'ed. | 533 // Maybe an old timer fired or we are already Close()'ed. |
| 534 if (!db_.get() || pending_operations_.empty()) | 534 if (!db_.get() || pending_operations_.empty()) |
| 535 return; | 535 return; |
| 536 | 536 |
| 537 sql::Statement add_stmt(db_->GetCachedStatement( | 537 sql::Statement add_stmt(db_->GetCachedStatement( |
| 538 SQL_FROM_HERE, | 538 SQL_FROM_HERE, |
| 539 "INSERT INTO webrtc_identity_store " | 539 "INSERT INTO webrtc_identity_store " |
| 540 "(origin, identity_name, common_name, certificate," | 540 "(origin, identity_name, common_name, certificate," |
| 541 " private_key, creation_time) VALUES" | 541 " private_key, creation_time) VALUES" |
| 542 " (?,?,?,?,?,?)")); | 542 " (?,?,?,?,?,?)")); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 NOTREACHED(); | 595 NOTREACHED(); |
| 596 break; | 596 break; |
| 597 } | 597 } |
| 598 } | 598 } |
| 599 | 599 |
| 600 if (!transaction.Commit()) | 600 if (!transaction.Commit()) |
| 601 DVLOG(2) << "Failed to commit the transaction."; | 601 DVLOG(2) << "Failed to commit the transaction."; |
| 602 } | 602 } |
| 603 | 603 |
| 604 } // namespace content | 604 } // namespace content |
| OLD | NEW |