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 |