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(); ++it) { 49 db_->AddTable(*it); 50 } 51 52 init_status_ = db_->Init(db_path_); 53 if (init_status_ != sql::INIT_OK) { 54 LOG(ERROR) << "Cannot initialize the web database: " << init_status_; 55 db_.reset(NULL); 56 return init_status_; 57 } 58 59 db_->BeginTransaction(); 60 return init_status_; 61 } 62 63 void WebDataServiceBackend::ShutdownDatabase() { 64 if (db_ && init_status_ == sql::INIT_OK) 65 db_->CommitTransaction(); 66 db_.reset(NULL); 67 init_complete_ = true; // Ensures the init sequence is not re-run. 68 init_status_ = sql::INIT_FAILURE; 69 } 70 71 void WebDataServiceBackend::DBWriteTaskWrapper( 72 const WebDatabaseService::WriteTask& task, 73 scoped_ptr<WebDataRequest> request) { 74 if (request->IsCancelled()) 75 return; 76 77 ExecuteWriteTask(task); 78 request_manager_->RequestCompleted(request.Pass()); 79 } 80 81 void WebDataServiceBackend::ExecuteWriteTask( 82 const WebDatabaseService::WriteTask& task) { 83 LoadDatabaseIfNecessary(); 84 if (db_ && init_status_ == sql::INIT_OK) { 85 WebDatabase::State state = task.Run(db_.get()); 86 if (state == WebDatabase::COMMIT_NEEDED) 87 Commit(); 88 } 89 } 90 91 void WebDataServiceBackend::DBReadTaskWrapper( 92 const WebDatabaseService::ReadTask& task, 93 scoped_ptr<WebDataRequest> request) { 94 if (request->IsCancelled()) 95 return; 96 97 request->SetResult(ExecuteReadTask(task).Pass()); 98 request_manager_->RequestCompleted(request.Pass()); 99 } 100 101 scoped_ptr<WDTypedResult> WebDataServiceBackend::ExecuteReadTask( 102 const WebDatabaseService::ReadTask& task) { 103 LoadDatabaseIfNecessary(); 104 if (db_ && init_status_ == sql::INIT_OK) { 105 return task.Run(db_.get()); 106 } 107 return scoped_ptr<WDTypedResult>(); 108 } 109 110 WebDataServiceBackend::~WebDataServiceBackend() { 111 ShutdownDatabase(); 112 } 113 114 void WebDataServiceBackend::Commit() { 115 DCHECK(db_); 116 DCHECK_EQ(sql::INIT_OK, init_status_); 117 db_->CommitTransaction(); 118 db_->BeginTransaction(); 119 } 120