| 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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 const std::vector<OfflinePageItem>& result) { | 282 const std::vector<OfflinePageItem>& result) { |
| 283 // TODO(fgorski): Switch to SQL specific UMA metrics. | 283 // TODO(fgorski): Switch to SQL specific UMA metrics. |
| 284 UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status, | 284 UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status, |
| 285 OfflinePageMetadataStore::LOAD_STATUS_COUNT); | 285 OfflinePageMetadataStore::LOAD_STATUS_COUNT); |
| 286 if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) { | 286 if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) { |
| 287 UMA_HISTOGRAM_COUNTS("OfflinePages.SavedPageCount", | 287 UMA_HISTOGRAM_COUNTS("OfflinePages.SavedPageCount", |
| 288 static_cast<int32_t>(result.size())); | 288 static_cast<int32_t>(result.size())); |
| 289 } else { | 289 } else { |
| 290 DVLOG(1) << "Offline pages database loading failed: " << status; | 290 DVLOG(1) << "Offline pages database loading failed: " << status; |
| 291 } | 291 } |
| 292 runner->PostTask(FROM_HERE, base::Bind(callback, status, result)); | 292 runner->PostTask(FROM_HERE, base::Bind(callback, result)); |
| 293 } | 293 } |
| 294 | 294 |
| 295 void OpenConnectionSync(sql::Connection* db, | 295 void OpenConnectionSync(sql::Connection* db, |
| 296 scoped_refptr<base::SingleThreadTaskRunner> runner, | 296 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 297 const base::FilePath& path, | 297 const base::FilePath& path, |
| 298 const base::Callback<void(StoreState)>& callback) { | 298 const base::Callback<void(bool)>& callback) { |
| 299 StoreState state = | 299 bool success = InitDatabase(db, path); |
| 300 InitDatabase(db, path) ? StoreState::LOADED : StoreState::FAILED_LOADING; | 300 runner->PostTask(FROM_HERE, base::Bind(callback, success)); |
| 301 runner->PostTask(FROM_HERE, base::Bind(callback, state)); | |
| 302 } | 301 } |
| 303 | 302 |
| 304 bool GetPageByOfflineIdSync(sql::Connection* db, | 303 bool GetPageByOfflineIdSync(sql::Connection* db, |
| 305 int64_t offline_id, | 304 int64_t offline_id, |
| 306 OfflinePageItem* item) { | 305 OfflinePageItem* item) { |
| 307 const char kSql[] = | 306 const char kSql[] = |
| 308 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; | 307 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; |
| 309 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 308 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 310 statement.BindInt64(0, offline_id); | 309 statement.BindInt64(0, offline_id); |
| 311 | 310 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 PostStoreErrorForAllIds(runner, offline_ids, callback); | 446 PostStoreErrorForAllIds(runner, offline_ids, callback); |
| 448 return; | 447 return; |
| 449 } | 448 } |
| 450 | 449 |
| 451 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); | 450 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); |
| 452 } | 451 } |
| 453 | 452 |
| 454 void ResetSync(sql::Connection* db, | 453 void ResetSync(sql::Connection* db, |
| 455 const base::FilePath& db_file_path, | 454 const base::FilePath& db_file_path, |
| 456 scoped_refptr<base::SingleThreadTaskRunner> runner, | 455 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 457 const base::Callback<void(StoreState)>& callback) { | 456 const base::Callback<void(bool)>& callback) { |
| 458 // This method deletes the content of the whole store and reinitializes it. | 457 // This method deletes the content of the whole store and reinitializes it. |
| 459 bool success = db->Raze(); | 458 bool success = true; |
| 460 db->Close(); | 459 if (db) { |
| 461 StoreState state; | 460 success = db->Raze(); |
| 462 if (success) { | 461 db->Close(); |
| 463 state = InitDatabase(db, db_file_path) ? StoreState::LOADED | |
| 464 : StoreState::FAILED_LOADING; | |
| 465 } else { | |
| 466 state = StoreState::FAILED_RESET; | |
| 467 } | 462 } |
| 468 runner->PostTask(FROM_HERE, base::Bind(callback, state)); | 463 success = base::DeleteFile(db_file_path, true /*recursive*/) && success; |
| 464 runner->PostTask(FROM_HERE, base::Bind(callback, success)); |
| 469 } | 465 } |
| 470 | 466 |
| 471 } // anonymous namespace | 467 } // anonymous namespace |
| 472 | 468 |
| 473 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL( | 469 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL( |
| 474 scoped_refptr<base::SequencedTaskRunner> background_task_runner, | 470 scoped_refptr<base::SequencedTaskRunner> background_task_runner, |
| 475 const base::FilePath& path) | 471 const base::FilePath& path) |
| 476 : background_task_runner_(std::move(background_task_runner)), | 472 : background_task_runner_(std::move(background_task_runner)), |
| 477 db_file_path_(path.AppendASCII("OfflinePages.db")), | 473 db_file_path_(path.AppendASCII("OfflinePages.db")), |
| 478 state_(StoreState::NOT_LOADED), | 474 state_(StoreState::NOT_LOADED), |
| 479 weak_ptr_factory_(this) { | 475 weak_ptr_factory_(this) { |
| 480 OpenConnection(); | |
| 481 } | 476 } |
| 482 | 477 |
| 483 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() { | 478 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() { |
| 484 if (db_.get() && | 479 if (db_.get() && |
| 485 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) { | 480 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) { |
| 486 DLOG(WARNING) << "SQL database will not be deleted."; | 481 DLOG(WARNING) << "SQL database will not be deleted."; |
| 487 } | 482 } |
| 488 } | 483 } |
| 489 | 484 |
| 485 void OfflinePageMetadataStoreSQL::Initialize( |
| 486 const InitializeCallback& callback) { |
| 487 DCHECK(!db_); |
| 488 db_.reset(new sql::Connection()); |
| 489 background_task_runner_->PostTask( |
| 490 FROM_HERE, |
| 491 base::Bind(&OpenConnectionSync, db_.get(), |
| 492 base::ThreadTaskRunnerHandle::Get(), db_file_path_, |
| 493 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone, |
| 494 weak_ptr_factory_.GetWeakPtr(), callback))); |
| 495 } |
| 496 |
| 490 void OfflinePageMetadataStoreSQL::GetOfflinePages( | 497 void OfflinePageMetadataStoreSQL::GetOfflinePages( |
| 491 const LoadCallback& callback) { | 498 const LoadCallback& callback) { |
| 492 if (!CheckDb(base::Bind( | 499 if (!CheckDb()) { |
| 493 callback, STORE_INIT_FAILED, std::vector<OfflinePageItem>()))) { | 500 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 501 FROM_HERE, base::Bind(callback, std::vector<OfflinePageItem>())); |
| 494 return; | 502 return; |
| 495 } | 503 } |
| 496 | 504 |
| 497 background_task_runner_->PostTask( | 505 background_task_runner_->PostTask( |
| 498 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(), | 506 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(), |
| 499 base::ThreadTaskRunnerHandle::Get(), callback)); | 507 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 500 } | 508 } |
| 501 | 509 |
| 502 void OfflinePageMetadataStoreSQL::AddOfflinePage( | 510 void OfflinePageMetadataStoreSQL::AddOfflinePage( |
| 503 const OfflinePageItem& offline_page, | 511 const OfflinePageItem& offline_page, |
| 504 const AddCallback& callback) { | 512 const AddCallback& callback) { |
| 505 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR))) | 513 if (!CheckDb()) { |
| 514 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 515 FROM_HERE, base::Bind(callback, ItemActionStatus::STORE_ERROR)); |
| 506 return; | 516 return; |
| 517 } |
| 507 | 518 |
| 508 background_task_runner_->PostTask( | 519 background_task_runner_->PostTask( |
| 509 FROM_HERE, | 520 FROM_HERE, |
| 510 base::Bind(&AddOfflinePageSync, db_.get(), | 521 base::Bind(&AddOfflinePageSync, db_.get(), |
| 511 base::ThreadTaskRunnerHandle::Get(), offline_page, callback)); | 522 base::ThreadTaskRunnerHandle::Get(), offline_page, callback)); |
| 512 } | 523 } |
| 513 | 524 |
| 514 void OfflinePageMetadataStoreSQL::UpdateOfflinePages( | 525 void OfflinePageMetadataStoreSQL::UpdateOfflinePages( |
| 515 const std::vector<OfflinePageItem>& pages, | 526 const std::vector<OfflinePageItem>& pages, |
| 516 const UpdateCallback& callback) { | 527 const UpdateCallback& callback) { |
| 517 if (!db_.get()) { | 528 if (!CheckDb()) { |
| 518 PostStoreErrorForAllPages(base::ThreadTaskRunnerHandle::Get(), pages, | 529 PostStoreErrorForAllPages(base::ThreadTaskRunnerHandle::Get(), pages, |
| 519 callback); | 530 callback); |
| 520 return; | 531 return; |
| 521 } | 532 } |
| 522 | 533 |
| 523 background_task_runner_->PostTask( | 534 background_task_runner_->PostTask( |
| 524 FROM_HERE, | 535 FROM_HERE, |
| 525 base::Bind(&UpdateOfflinePagesSync, db_.get(), | 536 base::Bind(&UpdateOfflinePagesSync, db_.get(), |
| 526 base::ThreadTaskRunnerHandle::Get(), pages, callback)); | 537 base::ThreadTaskRunnerHandle::Get(), pages, callback)); |
| 527 } | 538 } |
| 528 | 539 |
| 529 void OfflinePageMetadataStoreSQL::RemoveOfflinePages( | 540 void OfflinePageMetadataStoreSQL::RemoveOfflinePages( |
| 530 const std::vector<int64_t>& offline_ids, | 541 const std::vector<int64_t>& offline_ids, |
| 531 const UpdateCallback& callback) { | 542 const UpdateCallback& callback) { |
| 532 DCHECK(db_.get()); | 543 if (!CheckDb()) { |
| 544 PostStoreErrorForAllIds(base::ThreadTaskRunnerHandle::Get(), offline_ids, |
| 545 callback); |
| 546 return; |
| 547 } |
| 533 | 548 |
| 534 if (offline_ids.empty()) { | 549 if (offline_ids.empty()) { |
| 535 // Nothing to do, but post a callback instead of calling directly | 550 // Nothing to do, but post a callback instead of calling directly |
| 536 // to preserve the async style behavior to prevent bugs. | 551 // to preserve the async style behavior to prevent bugs. |
| 537 PostStoreUpdateResultForIds( | 552 PostStoreUpdateResultForIds( |
| 538 base::ThreadTaskRunnerHandle::Get(), state(), offline_ids, | 553 base::ThreadTaskRunnerHandle::Get(), state(), offline_ids, |
| 539 ItemActionStatus::NOT_FOUND /* will be ignored */, callback); | 554 ItemActionStatus::NOT_FOUND /* will be ignored */, callback); |
| 540 return; | 555 return; |
| 541 } | 556 } |
| 542 | 557 |
| 543 background_task_runner_->PostTask( | 558 background_task_runner_->PostTask( |
| 544 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(), | 559 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(), |
| 545 base::ThreadTaskRunnerHandle::Get(), callback)); | 560 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 546 } | 561 } |
| 547 | 562 |
| 548 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) { | 563 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) { |
| 549 if (!CheckDb(base::Bind(callback, false))) | |
| 550 return; | |
| 551 | |
| 552 background_task_runner_->PostTask( | 564 background_task_runner_->PostTask( |
| 553 FROM_HERE, | 565 FROM_HERE, |
| 554 base::Bind(&ResetSync, db_.get(), db_file_path_, | 566 base::Bind(&ResetSync, db_.get(), db_file_path_, |
| 555 base::ThreadTaskRunnerHandle::Get(), | 567 base::ThreadTaskRunnerHandle::Get(), |
| 556 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone, | 568 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone, |
| 557 weak_ptr_factory_.GetWeakPtr(), callback))); | 569 weak_ptr_factory_.GetWeakPtr(), callback))); |
| 558 } | 570 } |
| 559 | 571 |
| 560 StoreState OfflinePageMetadataStoreSQL::state() const { | 572 StoreState OfflinePageMetadataStoreSQL::state() const { |
| 561 return state_; | 573 return state_; |
| 562 } | 574 } |
| 563 | 575 |
| 564 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state, | 576 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state, |
| 565 bool reset_db) { | 577 bool reset_db) { |
| 566 state_ = state; | 578 state_ = state; |
| 567 if (reset_db) | 579 if (reset_db) |
| 568 db_.reset(nullptr); | 580 db_.reset(nullptr); |
| 569 } | 581 } |
| 570 | 582 |
| 571 void OfflinePageMetadataStoreSQL::OpenConnection() { | 583 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone( |
| 572 DCHECK(!db_); | 584 const InitializeCallback& callback, |
| 573 db_.reset(new sql::Connection()); | 585 bool success) { |
| 574 background_task_runner_->PostTask( | |
| 575 FROM_HERE, | |
| 576 base::Bind(&OpenConnectionSync, db_.get(), | |
| 577 base::ThreadTaskRunnerHandle::Get(), db_file_path_, | |
| 578 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone, | |
| 579 weak_ptr_factory_.GetWeakPtr()))); | |
| 580 } | |
| 581 | |
| 582 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone(StoreState state) { | |
| 583 DCHECK(db_.get()); | 586 DCHECK(db_.get()); |
| 584 | 587 state_ = success ? StoreState::LOADED : StoreState::FAILED_LOADING; |
| 585 state_ = state; | 588 callback.Run(success); |
| 586 | |
| 587 // Unfortunately we were not able to open DB connection. | |
| 588 if (state != StoreState::LOADED) | |
| 589 db_.reset(); | |
| 590 | |
| 591 // TODO(fgorski): This might be a place to start store recovery. Alternatively | |
| 592 // that can be attempted in the OfflinePageModel. | |
| 593 } | 589 } |
| 594 | 590 |
| 595 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback, | 591 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback, |
| 596 StoreState state) { | 592 bool success) { |
| 597 OnOpenConnectionDone(state); | 593 state_ = success ? StoreState::NOT_LOADED : StoreState::FAILED_RESET; |
| 598 callback.Run(state == StoreState::LOADED); | 594 db_.reset(); |
| 595 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 596 base::Bind(callback, success)); |
| 599 } | 597 } |
| 600 | 598 |
| 601 bool OfflinePageMetadataStoreSQL::CheckDb(const base::Closure& callback) { | 599 bool OfflinePageMetadataStoreSQL::CheckDb() { |
| 602 if (!db_.get() || state_ != StoreState::LOADED) { | 600 return db_ && state_ == StoreState::LOADED; |
| 603 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); | |
| 604 return false; | |
| 605 } | |
| 606 return true; | |
| 607 } | 601 } |
| 608 | 602 |
| 609 } // namespace offline_pages | 603 } // namespace offline_pages |
| OLD | NEW |