| 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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 } | 247 } |
| 248 if (!db->Open(path)) { | 248 if (!db->Open(path)) { |
| 249 LOG(ERROR) << "Failed to open database"; | 249 LOG(ERROR) << "Failed to open database"; |
| 250 return false; | 250 return false; |
| 251 } | 251 } |
| 252 db->Preload(); | 252 db->Preload(); |
| 253 | 253 |
| 254 return CreateSchema(db); | 254 return CreateSchema(db); |
| 255 } | 255 } |
| 256 | 256 |
| 257 void NotifyLoadResult(scoped_refptr<base::SingleThreadTaskRunner> runner, | |
| 258 const OfflinePageMetadataStore::LoadCallback& callback, | |
| 259 OfflinePageMetadataStore::LoadStatus status, | |
| 260 const std::vector<OfflinePageItem>& result) { | |
| 261 // TODO(bburns): Switch to SQL specific UMA metrics. | |
| 262 UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status, | |
| 263 OfflinePageMetadataStore::LOAD_STATUS_COUNT); | |
| 264 if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) { | |
| 265 UMA_HISTOGRAM_COUNTS("OfflinePages.SavedPageCount", | |
| 266 static_cast<int32_t>(result.size())); | |
| 267 } else { | |
| 268 DVLOG(1) << "Offline pages database loading failed: " << status; | |
| 269 } | |
| 270 runner->PostTask(FROM_HERE, base::Bind(callback, status, result)); | |
| 271 } | |
| 272 | |
| 273 void OpenConnectionSync(sql::Connection* db, | 257 void OpenConnectionSync(sql::Connection* db, |
| 274 scoped_refptr<base::SingleThreadTaskRunner> runner, | 258 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 275 const base::FilePath& path, | 259 const base::FilePath& path, |
| 276 const base::Callback<void(StoreState)>& callback) { | 260 const base::Callback<void(StoreState)>& callback) { |
| 277 StoreState state = | 261 StoreState state = |
| 278 InitDatabase(db, path) ? StoreState::LOADED : StoreState::FAILED_LOADING; | 262 InitDatabase(db, path) ? StoreState::LOADED : StoreState::FAILED_LOADING; |
| 279 runner->PostTask(FROM_HERE, base::Bind(callback, state)); | 263 runner->PostTask(FROM_HERE, base::Bind(callback, state)); |
| 280 } | 264 } |
| 281 | 265 |
| 282 bool GetPageByOfflineIdSync(sql::Connection* db, | 266 bool GetPageByOfflineIdSync(sql::Connection* db, |
| 283 int64_t offline_id, | 267 int64_t offline_id, |
| 284 OfflinePageItem* item) { | 268 OfflinePageItem* item) { |
| 285 const char kSql[] = | 269 const char kSql[] = |
| 286 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; | 270 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; |
| 287 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 271 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 288 statement.BindInt64(0, offline_id); | 272 statement.BindInt64(0, offline_id); |
| 289 | 273 |
| 290 if (statement.Step()) { | 274 if (statement.Step()) { |
| 291 *item = MakeOfflinePageItem(&statement); | 275 *item = MakeOfflinePageItem(&statement); |
| 292 return true; | 276 return true; |
| 293 } | 277 } |
| 294 | 278 |
| 295 return false; | 279 return false; |
| 296 } | 280 } |
| 297 | 281 |
| 298 void GetOfflinePagesSync( | 282 void GetOfflinePagesSync( |
| 299 sql::Connection* db, | 283 sql::Connection* db, |
| 300 scoped_refptr<base::SingleThreadTaskRunner> runner, | 284 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 301 const OfflinePageMetadataStore::LoadCallback& callback) { | 285 const OfflinePageMetadataStore::GetOfflinePagesCallback& callback) { |
| 302 const char kSql[] = "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME; | 286 const char kSql[] = "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME; |
| 303 | 287 |
| 304 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 288 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 305 | 289 |
| 306 std::vector<OfflinePageItem> result; | 290 std::vector<OfflinePageItem> result; |
| 307 while (statement.Step()) | 291 while (statement.Step()) |
| 308 result.push_back(MakeOfflinePageItem(&statement)); | 292 result.push_back(MakeOfflinePageItem(&statement)); |
| 309 | 293 |
| 310 if (statement.Succeeded()) { | 294 StoreState store_state = |
| 311 NotifyLoadResult(runner, callback, OfflinePageMetadataStore::LOAD_SUCCEEDED, | 295 statement.Succeeded() ? StoreState::LOADED : StoreState::FAILED_OPERATION; |
| 312 result); | 296 if (!statement.Succeeded()) |
| 313 } else { | |
| 314 result.clear(); | 297 result.clear(); |
| 315 NotifyLoadResult(runner, callback, | 298 |
| 316 OfflinePageMetadataStore::STORE_LOAD_FAILED, result); | 299 runner->PostTask(FROM_HERE, base::Bind(callback, store_state, result)); |
| 317 } | |
| 318 } | 300 } |
| 319 | 301 |
| 320 void AddOfflinePageSync(sql::Connection* db, | 302 void AddOfflinePageSync(sql::Connection* db, |
| 321 scoped_refptr<base::SingleThreadTaskRunner> runner, | 303 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 322 const OfflinePageItem& offline_page, | 304 const OfflinePageItem& offline_page, |
| 323 const OfflinePageMetadataStore::AddCallback& callback) { | 305 const OfflinePageMetadataStore::AddCallback& callback) { |
| 324 ItemActionStatus status = Insert(db, offline_page); | 306 ItemActionStatus status = Insert(db, offline_page); |
| 325 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | 307 runner->PostTask(FROM_HERE, base::Bind(callback, status)); |
| 326 } | 308 } |
| 327 | 309 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 } | 412 } |
| 431 | 413 |
| 432 void ResetSync(sql::Connection* db, | 414 void ResetSync(sql::Connection* db, |
| 433 const base::FilePath& db_file_path, | 415 const base::FilePath& db_file_path, |
| 434 scoped_refptr<base::SingleThreadTaskRunner> runner, | 416 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 435 const base::Callback<void(StoreState)>& callback) { | 417 const base::Callback<void(StoreState)>& callback) { |
| 436 // This method deletes the content of the whole store and reinitializes it. | 418 // This method deletes the content of the whole store and reinitializes it. |
| 437 bool success = db->Raze(); | 419 bool success = db->Raze(); |
| 438 db->Close(); | 420 db->Close(); |
| 439 StoreState state; | 421 StoreState state; |
| 440 if (success) { | 422 if (!success) |
| 441 state = InitDatabase(db, db_file_path) ? StoreState::LOADED | |
| 442 : StoreState::FAILED_LOADING; | |
| 443 } else { | |
| 444 state = StoreState::FAILED_RESET; | 423 state = StoreState::FAILED_RESET; |
| 445 } | 424 else if (InitDatabase(db, db_file_path)) |
| 425 state = StoreState::LOADED; |
| 426 else |
| 427 state = StoreState::FAILED_RESET; |
| 428 |
| 446 runner->PostTask(FROM_HERE, base::Bind(callback, state)); | 429 runner->PostTask(FROM_HERE, base::Bind(callback, state)); |
| 447 } | 430 } |
| 448 | 431 |
| 449 } // anonymous namespace | 432 } // anonymous namespace |
| 450 | 433 |
| 451 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL( | 434 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL( |
| 452 scoped_refptr<base::SequencedTaskRunner> background_task_runner, | 435 scoped_refptr<base::SequencedTaskRunner> background_task_runner, |
| 453 const base::FilePath& path) | 436 const base::FilePath& path) |
| 454 : background_task_runner_(std::move(background_task_runner)), | 437 : background_task_runner_(std::move(background_task_runner)), |
| 455 db_file_path_(path.AppendASCII("OfflinePages.db")), | 438 db_file_path_(path.AppendASCII("OfflinePages.db")), |
| 456 state_(StoreState::NOT_LOADED), | 439 state_(StoreState::NOT_LOADED), |
| 457 weak_ptr_factory_(this) { | 440 weak_ptr_factory_(this) { |
| 458 OpenConnection(); | 441 OpenConnection(); |
| 459 } | 442 } |
| 460 | 443 |
| 461 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() { | 444 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() { |
| 462 if (db_.get() && | 445 if (db_.get() && |
| 463 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) { | 446 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) { |
| 464 DLOG(WARNING) << "SQL database will not be deleted."; | 447 DLOG(WARNING) << "SQL database will not be deleted."; |
| 465 } | 448 } |
| 466 } | 449 } |
| 467 | 450 |
| 468 void OfflinePageMetadataStoreSQL::GetOfflinePages( | 451 void OfflinePageMetadataStoreSQL::GetOfflinePages( |
| 469 const LoadCallback& callback) { | 452 const GetOfflinePagesCallback& callback) { |
| 470 if (!CheckDb(base::Bind( | 453 if (!CheckStoreState()) { |
| 471 callback, STORE_INIT_FAILED, std::vector<OfflinePageItem>()))) { | 454 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 455 FROM_HERE, |
| 456 base::Bind(callback, state(), std::vector<OfflinePageItem>())); |
| 472 return; | 457 return; |
| 473 } | 458 } |
| 474 | 459 |
| 475 background_task_runner_->PostTask( | 460 background_task_runner_->PostTask( |
| 476 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(), | 461 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(), |
| 477 base::ThreadTaskRunnerHandle::Get(), callback)); | 462 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 478 } | 463 } |
| 479 | 464 |
| 480 void OfflinePageMetadataStoreSQL::AddOfflinePage( | 465 void OfflinePageMetadataStoreSQL::AddOfflinePage( |
| 481 const OfflinePageItem& offline_page, | 466 const OfflinePageItem& offline_page, |
| 482 const AddCallback& callback) { | 467 const AddCallback& callback) { |
| 483 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR))) | 468 if (!CheckStoreState()) { |
| 469 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 470 FROM_HERE, base::Bind(callback, ItemActionStatus::STORE_ERROR)); |
| 484 return; | 471 return; |
| 472 } |
| 485 | 473 |
| 486 background_task_runner_->PostTask( | 474 background_task_runner_->PostTask( |
| 487 FROM_HERE, | 475 FROM_HERE, |
| 488 base::Bind(&AddOfflinePageSync, db_.get(), | 476 base::Bind(&AddOfflinePageSync, db_.get(), |
| 489 base::ThreadTaskRunnerHandle::Get(), offline_page, callback)); | 477 base::ThreadTaskRunnerHandle::Get(), offline_page, callback)); |
| 490 } | 478 } |
| 491 | 479 |
| 492 void OfflinePageMetadataStoreSQL::UpdateOfflinePages( | 480 void OfflinePageMetadataStoreSQL::UpdateOfflinePages( |
| 493 const std::vector<OfflinePageItem>& pages, | 481 const std::vector<OfflinePageItem>& pages, |
| 494 const UpdateCallback& callback) { | 482 const UpdateCallback& callback) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 517 ItemActionStatus::NOT_FOUND /* will be ignored */, callback); | 505 ItemActionStatus::NOT_FOUND /* will be ignored */, callback); |
| 518 return; | 506 return; |
| 519 } | 507 } |
| 520 | 508 |
| 521 background_task_runner_->PostTask( | 509 background_task_runner_->PostTask( |
| 522 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(), | 510 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(), |
| 523 base::ThreadTaskRunnerHandle::Get(), callback)); | 511 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 524 } | 512 } |
| 525 | 513 |
| 526 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) { | 514 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) { |
| 527 if (!CheckDb(base::Bind(callback, false))) | 515 if (!CheckStoreState()) { |
| 516 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 517 base::Bind(callback, false)); |
| 528 return; | 518 return; |
| 519 } |
| 529 | 520 |
| 530 background_task_runner_->PostTask( | 521 background_task_runner_->PostTask( |
| 531 FROM_HERE, | 522 FROM_HERE, |
| 532 base::Bind(&ResetSync, db_.get(), db_file_path_, | 523 base::Bind(&ResetSync, db_.get(), db_file_path_, |
| 533 base::ThreadTaskRunnerHandle::Get(), | 524 base::ThreadTaskRunnerHandle::Get(), |
| 534 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone, | 525 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone, |
| 535 weak_ptr_factory_.GetWeakPtr(), callback))); | 526 weak_ptr_factory_.GetWeakPtr(), callback))); |
| 536 } | 527 } |
| 537 | 528 |
| 538 StoreState OfflinePageMetadataStoreSQL::state() const { | |
| 539 return state_; | |
| 540 } | |
| 541 | |
| 542 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state, | |
| 543 bool reset_db) { | |
| 544 state_ = state; | |
| 545 if (reset_db) | |
| 546 db_.reset(nullptr); | |
| 547 } | |
| 548 | |
| 549 void OfflinePageMetadataStoreSQL::OpenConnection() { | 529 void OfflinePageMetadataStoreSQL::OpenConnection() { |
| 550 DCHECK(!db_); | 530 DCHECK(!db_); |
| 551 db_.reset(new sql::Connection()); | 531 db_.reset(new sql::Connection()); |
| 552 background_task_runner_->PostTask( | 532 background_task_runner_->PostTask( |
| 553 FROM_HERE, | 533 FROM_HERE, |
| 554 base::Bind(&OpenConnectionSync, db_.get(), | 534 base::Bind(&OpenConnectionSync, db_.get(), |
| 555 base::ThreadTaskRunnerHandle::Get(), db_file_path_, | 535 base::ThreadTaskRunnerHandle::Get(), db_file_path_, |
| 556 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone, | 536 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone, |
| 557 weak_ptr_factory_.GetWeakPtr()))); | 537 weak_ptr_factory_.GetWeakPtr()))); |
| 558 } | 538 } |
| 559 | 539 |
| 560 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone(StoreState state) { | 540 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone(StoreState state) { |
| 561 DCHECK(db_.get()); | 541 DCHECK(db_.get()); |
| 562 | 542 |
| 563 state_ = state; | 543 state_ = state; |
| 564 | 544 |
| 565 // Unfortunately we were not able to open DB connection. | 545 // Unfortunately we were not able to open DB connection. |
| 566 if (state != StoreState::LOADED) | 546 if (state != StoreState::LOADED) |
| 567 db_.reset(); | 547 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 } | 548 } |
| 572 | 549 |
| 573 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback, | 550 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback, |
| 574 StoreState state) { | 551 StoreState state) { |
| 575 OnOpenConnectionDone(state); | 552 OnOpenConnectionDone(state); |
| 576 callback.Run(state == StoreState::LOADED); | 553 callback.Run(state == StoreState::LOADED); |
| 577 } | 554 } |
| 578 | 555 |
| 579 bool OfflinePageMetadataStoreSQL::CheckDb(const base::Closure& callback) { | 556 bool OfflinePageMetadataStoreSQL::CheckStoreState() { |
| 580 if (!db_.get() || state_ != StoreState::LOADED) { | 557 // If db is null, store cannot be loaded. |
| 581 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); | 558 DCHECK(db_.get() || state_ != StoreState::LOADED); |
| 582 return false; | 559 return db_.get() && state_ == StoreState::LOADED; |
| 583 } | 560 } |
| 584 return true; | 561 |
| 562 StoreState OfflinePageMetadataStoreSQL::state() const { |
| 563 return state_; |
| 564 } |
| 565 |
| 566 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state, |
| 567 bool reset_db) { |
| 568 state_ = state; |
| 569 if (reset_db) |
| 570 db_.reset(nullptr); |
| 585 } | 571 } |
| 586 | 572 |
| 587 } // namespace offline_pages | 573 } // namespace offline_pages |
| OLD | NEW |