web_database_backend.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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
  3. // found in the LICENSE file.
  4. #include "components/webdata/common/web_database_backend.h"
  5. #include <algorithm>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/location.h"
  9. #include "components/webdata/common/web_data_request_manager.h"
  10. #include "components/webdata/common/web_database.h"
  11. #include "components/webdata/common/web_database_table.h"
  12. #include "sql/error_delegate_util.h"
  13. WebDatabaseBackend::WebDatabaseBackend(
  14. const base::FilePath& path,
  15. std::unique_ptr<Delegate> delegate,
  16. const scoped_refptr<base::SingleThreadTaskRunner>& db_thread)
  17. : base::RefCountedDeleteOnSequence<WebDatabaseBackend>(db_thread),
  18. db_path_(path),
  19. delegate_(std::move(delegate)) {}
  20. void WebDatabaseBackend::AddTable(std::unique_ptr<WebDatabaseTable> table) {
  21. DCHECK(!db_);
  22. tables_.push_back(std::move(table));
  23. }
  24. void WebDatabaseBackend::InitDatabase() {
  25. LoadDatabaseIfNecessary();
  26. if (delegate_)
  27. delegate_->DBLoaded(init_status_, diagnostics_);
  28. }
  29. void WebDatabaseBackend::ShutdownDatabase() {
  30. if (db_ && init_status_ == sql::INIT_OK)
  31. db_->CommitTransaction();
  32. db_.reset();
  33. init_complete_ = true; // Ensures the init sequence is not re-run.
  34. init_status_ = sql::INIT_FAILURE;
  35. }
  36. void WebDatabaseBackend::DBWriteTaskWrapper(
  37. WebDatabaseService::WriteTask task,
  38. std::unique_ptr<WebDataRequest> request) {
  39. if (!request->IsActive())
  40. return;
  41. ExecuteWriteTask(std::move(task));
  42. request_manager_->RequestCompleted(std::move(request), nullptr);
  43. }
  44. void WebDatabaseBackend::ExecuteWriteTask(WebDatabaseService::WriteTask task) {
  45. LoadDatabaseIfNecessary();
  46. if (db_ && init_status_ == sql::INIT_OK) {
  47. WebDatabase::State state = std::move(task).Run(db_.get());
  48. if (state == WebDatabase::COMMIT_NEEDED)
  49. Commit();
  50. }
  51. }
  52. void WebDatabaseBackend::DBReadTaskWrapper(
  53. WebDatabaseService::ReadTask task,
  54. std::unique_ptr<WebDataRequest> request) {
  55. if (!request->IsActive())
  56. return;
  57. std::unique_ptr<WDTypedResult> result = ExecuteReadTask(std::move(task));
  58. request_manager_->RequestCompleted(std::move(request), std::move(result));
  59. }
  60. std::unique_ptr<WDTypedResult> WebDatabaseBackend::ExecuteReadTask(
  61. WebDatabaseService::ReadTask task) {
  62. LoadDatabaseIfNecessary();
  63. return (db_ && init_status_ == sql::INIT_OK) ? std::move(task).Run(db_.get())
  64. : nullptr;
  65. }
  66. WebDatabaseBackend::~WebDatabaseBackend() {
  67. ShutdownDatabase();
  68. }
  69. void WebDatabaseBackend::LoadDatabaseIfNecessary() {
  70. if (init_complete_ || db_path_.empty())
  71. return;
  72. init_complete_ = true;
  73. db_ = std::make_unique<WebDatabase>();
  74. for (const auto& table : tables_)
  75. db_->AddTable(table.get());
  76. // Unretained to avoid a ref loop since we own |db_|.
  77. db_->set_error_callback(base::BindRepeating(
  78. &WebDatabaseBackend::DatabaseErrorCallback, base::Unretained(this)));
  79. diagnostics_.clear();
  80. catastrophic_error_occurred_ = false;
  81. init_status_ = db_->Init(db_path_);
  82. if (init_status_ != sql::INIT_OK) {
  83. db_.reset();
  84. return;
  85. }
  86. // A catastrophic error might have happened and recovered.
  87. if (catastrophic_error_occurred_)
  88. init_status_ = sql::INIT_OK_WITH_DATA_LOSS;
  89. db_->BeginTransaction();
  90. }
  91. void WebDatabaseBackend::DatabaseErrorCallback(int error,
  92. sql::Statement* statement) {
  93. // We ignore any further error callbacks after the first catastrophic error.
  94. if (!catastrophic_error_occurred_ && sql::IsErrorCatastrophic(error)) {
  95. catastrophic_error_occurred_ = true;
  96. diagnostics_ = db_->GetDiagnosticInfo(error, statement);
  97. diagnostics_ += sql::GetCorruptFileDiagnosticsInfo(db_path_);
  98. db_->GetSQLConnection()->RazeAndClose();
  99. }
  100. }
  101. void WebDatabaseBackend::Commit() {
  102. DCHECK(db_);
  103. DCHECK_EQ(sql::INIT_OK, init_status_);
  104. db_->CommitTransaction();
  105. db_->BeginTransaction();
  106. }