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 5#include "components/webdata/common/web_data_service_backend.h" 6 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 13using base::Bind; 14using base::FilePath; 15 16WebDataServiceBackend::WebDataServiceBackend( 17 const FilePath& path, 18 Delegate* delegate, 19 const scoped_refptr<base::MessageLoopProxy>& db_thread) 20 : base::RefCountedDeleteOnMessageLoop<WebDataServiceBackend>(db_thread), 21 db_path_(path), 22 request_manager_(new WebDataRequestManager()), 23 init_status_(sql::INIT_FAILURE), 24 init_complete_(false), 25 delegate_(delegate) { 26} 27 28void WebDataServiceBackend::AddTable(scoped_ptr<WebDatabaseTable> table) { 29 DCHECK(!db_.get()); 30 tables_.push_back(table.release()); 31} 32 33void WebDataServiceBackend::InitDatabase() { 34 LoadDatabaseIfNecessary(); 35 if (delegate_) { 36 delegate_->DBLoaded(init_status_); 37 } 38} 39 40sql::InitStatus WebDataServiceBackend::LoadDatabaseIfNecessary() { 41 if (init_complete_ || db_path_.empty()) { 42 return init_status_; 43 } 44 init_complete_ = true; 45 db_.reset(new WebDatabase()); 46 47 for (ScopedVector<WebDatabaseTable>::iterator it = tables_.begin(); 48 it != tables_.end(); 49 ++it) { 50 db_->AddTable(*it); 51 } 52 53 init_status_ = db_->Init(db_path_); 54 if (init_status_ != sql::INIT_OK) { 55 LOG(ERROR) << "Cannot initialize the web database: " << init_status_; 56 db_.reset(NULL); 57 return init_status_; 58 } 59 60 db_->BeginTransaction(); 61 return init_status_; 62} 63 64void WebDataServiceBackend::ShutdownDatabase(bool should_reinit) { 65 if (db_ && init_status_ == sql::INIT_OK) 66 db_->CommitTransaction(); 67 db_.reset(NULL); 68 init_complete_ = !should_reinit; // Setting init_complete_ to true will ensure 69 // that the init sequence is not re-run. 70 71 init_status_ = sql::INIT_FAILURE; 72} 73 74void WebDataServiceBackend::DBWriteTaskWrapper( 75 const WebDatabaseService::WriteTask& task, 76 scoped_ptr<WebDataRequest> request) { 77 if (request->IsCancelled()) 78 return; 79 80 ExecuteWriteTask(task); 81 request_manager_->RequestCompleted(request.Pass()); 82} 83 84void WebDataServiceBackend::ExecuteWriteTask( 85 const WebDatabaseService::WriteTask& task) { 86 LoadDatabaseIfNecessary(); 87 if (db_ && init_status_ == sql::INIT_OK) { 88 WebDatabase::State state = task.Run(db_.get()); 89 if (state == WebDatabase::COMMIT_NEEDED) 90 Commit(); 91 } 92} 93 94void WebDataServiceBackend::DBReadTaskWrapper( 95 const WebDatabaseService::ReadTask& task, 96 scoped_ptr<WebDataRequest> request) { 97 if (request->IsCancelled()) 98 return; 99 100 request->SetResult(ExecuteReadTask(task).Pass()); 101 request_manager_->RequestCompleted(request.Pass()); 102} 103 104scoped_ptr<WDTypedResult> WebDataServiceBackend::ExecuteReadTask( 105 const WebDatabaseService::ReadTask& task) { 106 LoadDatabaseIfNecessary(); 107 if (db_ && init_status_ == sql::INIT_OK) { 108 return task.Run(db_.get()); 109 } 110 return scoped_ptr<WDTypedResult>(); 111} 112 113WebDataServiceBackend::~WebDataServiceBackend() { 114 ShutdownDatabase(false); 115} 116 117void WebDataServiceBackend::Commit() { 118 if (db_ && init_status_ == sql::INIT_OK) { 119 db_->CommitTransaction(); 120 db_->BeginTransaction(); 121 } else { 122 NOTREACHED() << "Commit scheduled after Shutdown()"; 123 } 124} 125