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 13 using base::Bind; 14 using base::FilePath; 15 16 WebDataServiceBackend::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 28 void WebDataServiceBackend::AddTable(scoped_ptr<WebDatabaseTable> table) { 29 DCHECK(!db_.get()); 30 tables_.push_back(table.release()); 31 } 32 33 void WebDataServiceBackend::InitDatabase() { 34 LoadDatabaseIfNecessary(); 35 if (delegate_) { 36 delegate_->DBLoaded(init_status_); 37 } 38 } 39 40 sql::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 64 void 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 74 void 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 84 void 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 94 void 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 104 scoped_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 113 WebDataServiceBackend::~WebDataServiceBackend() { 114 ShutdownDatabase(false); 115 } 116 117 void 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