Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/offline_pages/offline_page_metadata_store_sql.h" | 5 #include "components/offline_pages/offline_page_metadata_store_sql.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 const std::vector<OfflinePageItem>& result) { | 260 const std::vector<OfflinePageItem>& result) { |
| 261 // TODO(fgorski): Switch to SQL specific UMA metrics. | 261 // TODO(fgorski): Switch to SQL specific UMA metrics. |
| 262 UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status, | 262 UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status, |
| 263 OfflinePageMetadataStore::LOAD_STATUS_COUNT); | 263 OfflinePageMetadataStore::LOAD_STATUS_COUNT); |
| 264 if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) { | 264 if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) { |
| 265 UMA_HISTOGRAM_COUNTS("OfflinePages.SavedPageCount", | 265 UMA_HISTOGRAM_COUNTS("OfflinePages.SavedPageCount", |
| 266 static_cast<int32_t>(result.size())); | 266 static_cast<int32_t>(result.size())); |
| 267 } else { | 267 } else { |
| 268 DVLOG(1) << "Offline pages database loading failed: " << status; | 268 DVLOG(1) << "Offline pages database loading failed: " << status; |
| 269 } | 269 } |
| 270 runner->PostTask(FROM_HERE, base::Bind(callback, status, result)); | 270 runner->PostTask(FROM_HERE, base::Bind(callback, result)); |
| 271 } | 271 } |
| 272 | 272 |
| 273 void OpenConnectionSync(sql::Connection* db, | 273 void OpenConnectionSync(sql::Connection* db, |
| 274 scoped_refptr<base::SingleThreadTaskRunner> runner, | 274 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 275 const base::FilePath& path, | 275 const base::FilePath& path, |
| 276 const base::Callback<void(StoreState)>& callback) { | 276 const base::Callback<void(bool)>& callback) { |
| 277 StoreState state = | 277 bool success = InitDatabase(db, path); |
| 278 InitDatabase(db, path) ? StoreState::LOADED : StoreState::FAILED_LOADING; | 278 runner->PostTask(FROM_HERE, base::Bind(callback, success)); |
| 279 runner->PostTask(FROM_HERE, base::Bind(callback, state)); | |
| 280 } | 279 } |
| 281 | 280 |
| 282 bool GetPageByOfflineIdSync(sql::Connection* db, | 281 bool GetPageByOfflineIdSync(sql::Connection* db, |
| 283 int64_t offline_id, | 282 int64_t offline_id, |
| 284 OfflinePageItem* item) { | 283 OfflinePageItem* item) { |
| 285 const char kSql[] = | 284 const char kSql[] = |
| 286 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; | 285 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; |
| 287 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 286 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 288 statement.BindInt64(0, offline_id); | 287 statement.BindInt64(0, offline_id); |
| 289 | 288 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 PostStoreErrorForAllIds(runner, offline_ids, callback); | 424 PostStoreErrorForAllIds(runner, offline_ids, callback); |
| 426 return; | 425 return; |
| 427 } | 426 } |
| 428 | 427 |
| 429 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); | 428 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); |
| 430 } | 429 } |
| 431 | 430 |
| 432 void ResetSync(sql::Connection* db, | 431 void ResetSync(sql::Connection* db, |
| 433 const base::FilePath& db_file_path, | 432 const base::FilePath& db_file_path, |
| 434 scoped_refptr<base::SingleThreadTaskRunner> runner, | 433 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 435 const base::Callback<void(StoreState)>& callback) { | 434 const base::Callback<void(bool)>& callback) { |
| 436 // This method deletes the content of the whole store and reinitializes it. | 435 // This method deletes the content of the whole store and reinitializes it. |
| 437 bool success = db->Raze(); | 436 bool success = true; |
| 438 db->Close(); | 437 if (db) { |
| 439 StoreState state; | 438 success = db->Raze(); |
| 440 if (success) { | 439 db->Close(); |
| 441 state = InitDatabase(db, db_file_path) ? StoreState::LOADED | |
| 442 : StoreState::FAILED_LOADING; | |
| 443 } else { | |
| 444 state = StoreState::FAILED_RESET; | |
| 445 } | 440 } |
| 446 runner->PostTask(FROM_HERE, base::Bind(callback, state)); | 441 success = base::DeleteFile(db_file_path, true /*recursive*/) && success; |
| 442 runner->PostTask(FROM_HERE, base::Bind(callback, success)); | |
| 447 } | 443 } |
| 448 | 444 |
| 449 } // anonymous namespace | 445 } // anonymous namespace |
| 450 | 446 |
| 451 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL( | 447 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL( |
| 452 scoped_refptr<base::SequencedTaskRunner> background_task_runner, | 448 scoped_refptr<base::SequencedTaskRunner> background_task_runner, |
| 453 const base::FilePath& path) | 449 const base::FilePath& path) |
| 454 : background_task_runner_(std::move(background_task_runner)), | 450 : background_task_runner_(std::move(background_task_runner)), |
| 455 db_file_path_(path.AppendASCII("OfflinePages.db")), | 451 db_file_path_(path.AppendASCII("OfflinePages.db")), |
| 456 state_(StoreState::NOT_LOADED), | 452 state_(StoreState::NOT_LOADED), |
| 457 weak_ptr_factory_(this) { | 453 weak_ptr_factory_(this) { |
| 458 OpenConnection(); | |
| 459 } | 454 } |
| 460 | 455 |
| 461 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() { | 456 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() { |
| 462 if (db_.get() && | 457 if (db_.get() && |
| 463 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) { | 458 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) { |
| 464 DLOG(WARNING) << "SQL database will not be deleted."; | 459 DLOG(WARNING) << "SQL database will not be deleted."; |
| 465 } | 460 } |
| 466 } | 461 } |
| 467 | 462 |
| 463 void OfflinePageMetadataStoreSQL::Initialize( | |
| 464 const InitializeCallback& callback) { | |
| 465 DCHECK(!db_); | |
| 466 db_.reset(new sql::Connection()); | |
| 467 background_task_runner_->PostTask( | |
| 468 FROM_HERE, | |
| 469 base::Bind(&OpenConnectionSync, db_.get(), | |
| 470 base::ThreadTaskRunnerHandle::Get(), db_file_path_, | |
| 471 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone, | |
| 472 weak_ptr_factory_.GetWeakPtr(), callback))); | |
| 473 } | |
| 474 | |
| 468 void OfflinePageMetadataStoreSQL::GetOfflinePages( | 475 void OfflinePageMetadataStoreSQL::GetOfflinePages( |
| 469 const LoadCallback& callback) { | 476 const LoadCallback& callback) { |
| 470 if (!CheckDb(base::Bind( | 477 if (!CheckDb()) { |
| 471 callback, STORE_INIT_FAILED, std::vector<OfflinePageItem>()))) { | 478 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 479 FROM_HERE, base::Bind(callback, std::vector<OfflinePageItem>())); | |
| 472 return; | 480 return; |
| 473 } | 481 } |
| 474 | 482 |
| 475 background_task_runner_->PostTask( | 483 background_task_runner_->PostTask( |
| 476 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(), | 484 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(), |
| 477 base::ThreadTaskRunnerHandle::Get(), callback)); | 485 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 478 } | 486 } |
| 479 | 487 |
| 480 void OfflinePageMetadataStoreSQL::AddOfflinePage( | 488 void OfflinePageMetadataStoreSQL::AddOfflinePage( |
| 481 const OfflinePageItem& offline_page, | 489 const OfflinePageItem& offline_page, |
| 482 const AddCallback& callback) { | 490 const AddCallback& callback) { |
| 483 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR))) | 491 if (!CheckDb()) { |
| 492 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 493 FROM_HERE, base::Bind(callback, ItemActionStatus::STORE_ERROR)); | |
| 484 return; | 494 return; |
| 495 } | |
| 485 | 496 |
| 486 background_task_runner_->PostTask( | 497 background_task_runner_->PostTask( |
| 487 FROM_HERE, | 498 FROM_HERE, |
| 488 base::Bind(&AddOfflinePageSync, db_.get(), | 499 base::Bind(&AddOfflinePageSync, db_.get(), |
| 489 base::ThreadTaskRunnerHandle::Get(), offline_page, callback)); | 500 base::ThreadTaskRunnerHandle::Get(), offline_page, callback)); |
| 490 } | 501 } |
| 491 | 502 |
| 492 void OfflinePageMetadataStoreSQL::UpdateOfflinePages( | 503 void OfflinePageMetadataStoreSQL::UpdateOfflinePages( |
| 493 const std::vector<OfflinePageItem>& pages, | 504 const std::vector<OfflinePageItem>& pages, |
| 494 const UpdateCallback& callback) { | 505 const UpdateCallback& callback) { |
| 495 if (!db_.get()) { | 506 if (!CheckDb()) { |
| 496 PostStoreErrorForAllPages(base::ThreadTaskRunnerHandle::Get(), pages, | 507 PostStoreErrorForAllPages(base::ThreadTaskRunnerHandle::Get(), pages, |
| 497 callback); | 508 callback); |
| 498 return; | 509 return; |
| 499 } | 510 } |
| 500 | 511 |
| 501 background_task_runner_->PostTask( | 512 background_task_runner_->PostTask( |
| 502 FROM_HERE, | 513 FROM_HERE, |
| 503 base::Bind(&UpdateOfflinePagesSync, db_.get(), | 514 base::Bind(&UpdateOfflinePagesSync, db_.get(), |
| 504 base::ThreadTaskRunnerHandle::Get(), pages, callback)); | 515 base::ThreadTaskRunnerHandle::Get(), pages, callback)); |
| 505 } | 516 } |
| 506 | 517 |
| 507 void OfflinePageMetadataStoreSQL::RemoveOfflinePages( | 518 void OfflinePageMetadataStoreSQL::RemoveOfflinePages( |
| 508 const std::vector<int64_t>& offline_ids, | 519 const std::vector<int64_t>& offline_ids, |
| 509 const UpdateCallback& callback) { | 520 const UpdateCallback& callback) { |
| 510 DCHECK(db_.get()); | 521 if (!CheckDb()) { |
| 522 PostStoreErrorForAllIds(base::ThreadTaskRunnerHandle::Get(), offline_ids, | |
| 523 callback); | |
| 524 return; | |
| 525 } | |
| 511 | 526 |
| 512 if (offline_ids.empty()) { | 527 if (offline_ids.empty()) { |
| 513 // Nothing to do, but post a callback instead of calling directly | 528 // Nothing to do, but post a callback instead of calling directly |
| 514 // to preserve the async style behavior to prevent bugs. | 529 // to preserve the async style behavior to prevent bugs. |
| 515 PostStoreUpdateResultForIds( | 530 PostStoreUpdateResultForIds( |
| 516 base::ThreadTaskRunnerHandle::Get(), state(), offline_ids, | 531 base::ThreadTaskRunnerHandle::Get(), state(), offline_ids, |
| 517 ItemActionStatus::NOT_FOUND /* will be ignored */, callback); | 532 ItemActionStatus::NOT_FOUND /* will be ignored */, callback); |
| 518 return; | 533 return; |
| 519 } | 534 } |
| 520 | 535 |
| 521 background_task_runner_->PostTask( | 536 background_task_runner_->PostTask( |
| 522 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(), | 537 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(), |
| 523 base::ThreadTaskRunnerHandle::Get(), callback)); | 538 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 524 } | 539 } |
| 525 | 540 |
| 526 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) { | 541 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) { |
| 527 if (!CheckDb(base::Bind(callback, false))) | |
| 528 return; | |
| 529 | |
| 530 background_task_runner_->PostTask( | 542 background_task_runner_->PostTask( |
| 531 FROM_HERE, | 543 FROM_HERE, |
| 532 base::Bind(&ResetSync, db_.get(), db_file_path_, | 544 base::Bind(&ResetSync, db_.get(), db_file_path_, |
| 533 base::ThreadTaskRunnerHandle::Get(), | 545 base::ThreadTaskRunnerHandle::Get(), |
| 534 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone, | 546 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone, |
| 535 weak_ptr_factory_.GetWeakPtr(), callback))); | 547 weak_ptr_factory_.GetWeakPtr(), callback))); |
| 536 } | 548 } |
| 537 | 549 |
| 538 StoreState OfflinePageMetadataStoreSQL::state() const { | 550 StoreState OfflinePageMetadataStoreSQL::state() const { |
| 539 return state_; | 551 return state_; |
| 540 } | 552 } |
| 541 | 553 |
| 542 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state, | 554 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state, |
| 543 bool reset_db) { | 555 bool reset_db) { |
| 544 state_ = state; | 556 state_ = state; |
| 545 if (reset_db) | 557 if (reset_db) |
| 546 db_.reset(nullptr); | 558 db_.reset(nullptr); |
| 547 } | 559 } |
| 548 | 560 |
| 549 void OfflinePageMetadataStoreSQL::OpenConnection() { | 561 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone( |
| 550 DCHECK(!db_); | 562 const InitializeCallback& callback, |
| 551 db_.reset(new sql::Connection()); | 563 bool success) { |
| 552 background_task_runner_->PostTask( | |
| 553 FROM_HERE, | |
| 554 base::Bind(&OpenConnectionSync, db_.get(), | |
| 555 base::ThreadTaskRunnerHandle::Get(), db_file_path_, | |
| 556 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone, | |
| 557 weak_ptr_factory_.GetWeakPtr()))); | |
| 558 } | |
| 559 | |
| 560 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone(StoreState state) { | |
| 561 DCHECK(db_.get()); | 564 DCHECK(db_.get()); |
| 562 | 565 state_ = success ? StoreState::LOADED : StoreState::FAILED_LOADING; |
| 563 state_ = state; | 566 callback.Run(success); |
| 564 | |
| 565 // Unfortunately we were not able to open DB connection. | |
| 566 if (state != StoreState::LOADED) | |
| 567 db_.reset(); | |
| 568 | |
| 569 // TODO(fgorski): This might be a place to start store recovery. Alternatively | |
| 570 // that can be attempted in the OfflinePageModel. | |
| 571 } | 567 } |
| 572 | 568 |
| 573 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback, | 569 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback, |
| 574 StoreState state) { | 570 bool success) { |
| 575 OnOpenConnectionDone(state); | 571 state_ = success ? StoreState::NOT_LOADED : StoreState::FAILED_RESET; |
| 576 callback.Run(state == StoreState::LOADED); | 572 db_.reset(nullptr); |
|
jianli
2016/11/16 01:34:50
nit: do we really need nullptr?
fgorski
2016/11/16 19:10:13
Looks like we don't. I thought that this was C++17
| |
| 573 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
| 574 base::Bind(callback, success)); | |
| 577 } | 575 } |
| 578 | 576 |
| 579 bool OfflinePageMetadataStoreSQL::CheckDb(const base::Closure& callback) { | 577 bool OfflinePageMetadataStoreSQL::CheckDb() { |
| 580 if (!db_.get() || state_ != StoreState::LOADED) { | 578 return db_ && state_ == StoreState::LOADED; |
| 581 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); | |
| 582 return false; | |
| 583 } | |
| 584 return true; | |
| 585 } | 579 } |
| 586 | 580 |
| 587 } // namespace offline_pages | 581 } // namespace offline_pages |
| OLD | NEW |