Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 "chrome/browser/webdata/web_database_service.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/location.h" | |
| 9 #include "chrome/browser/api/webdata/web_data_results.h" | |
| 10 #include "chrome/browser/api/webdata/web_data_service_consumer.h" | |
| 11 #include "chrome/browser/webdata/web_data_request_manager.h" | |
| 12 #include "chrome/browser/webdata/web_data_service.h" | |
| 13 // TODO(caitkp): Remove this autofill dependency. | |
| 14 #include "components/autofill/browser/autofill_country.h" | |
| 15 | |
| 16 using base::Bind; | |
| 17 using base::FilePath; | |
| 18 using content::BrowserThread; | |
| 19 | |
| 20 | |
| 21 //////////////////////////////////////////////////////////////////////////////// | |
| 22 // | |
| 23 // WebDatabaseServiceInternal implementation. | |
| 24 // | |
| 25 //////////////////////////////////////////////////////////////////////////////// | |
| 26 | |
| 27 // Refcounted to allow asynchronous destruction on the DB thread. | |
| 28 class WebDatabaseServiceInternal | |
| 29 : public base::RefCountedThreadSafe<WebDatabaseServiceInternal, | |
| 30 BrowserThread::DeleteOnDBThread> { | |
| 31 public: | |
| 32 explicit WebDatabaseServiceInternal(const FilePath& path); | |
| 33 | |
| 34 // Initializes the database and notifies caller via callback when complete. | |
| 35 // Callback is called synchronously. | |
| 36 void InitDatabaseWithCallback( | |
| 37 const WebDatabaseService::InitCallback& callback); | |
| 38 | |
| 39 // Opens the database file from the profile path if an init has not yet been | |
| 40 // attempted. Separated from the constructor to ease construction/destruction | |
| 41 // of this object on one thread but database access on the DB thread. Returns | |
| 42 // the status of the database. | |
| 43 sql::InitStatus LoadDatabaseIfNecessary(); | |
| 44 | |
| 45 // Shuts down database. |should_reinit| tells us whether or not it should be | |
| 46 // possible to re-initialize the DB after the shutdown. | |
| 47 void ShutdownDatabase(bool should_reinit); | |
| 48 | |
| 49 // Task wrappers to run database tasks. | |
| 50 void DBWriteTaskWrapper( | |
| 51 const WebDatabaseService::WriteTask& task, | |
| 52 scoped_ptr<WebDataRequest> request); | |
| 53 void DBReadTaskWrapper( | |
| 54 const WebDatabaseService::ReadTask& task, | |
| 55 scoped_ptr<WebDataRequest> request); | |
| 56 | |
| 57 const scoped_refptr<WebDataRequestManager>& request_manager() { | |
| 58 return request_manager_; | |
| 59 } | |
| 60 | |
| 61 WebDatabase* database() { return db_.get(); } | |
| 62 | |
| 63 private: | |
| 64 friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>; | |
| 65 friend class base::DeleteHelper<WebDatabaseServiceInternal>; | |
| 66 | |
| 67 virtual ~WebDatabaseServiceInternal(); | |
| 68 | |
| 69 // Commit the current transaction. | |
| 70 void Commit(); | |
| 71 | |
| 72 // Path to database file. | |
| 73 FilePath db_path_; | |
| 74 | |
| 75 scoped_ptr<WebDatabase> db_; | |
| 76 | |
| 77 // Keeps track of all pending requests made to the db. | |
| 78 scoped_refptr<WebDataRequestManager> request_manager_; | |
| 79 | |
| 80 // State of database initialization. Used to prevent the executing of tasks | |
| 81 // before the db is ready. | |
| 82 sql::InitStatus init_status_; | |
| 83 | |
| 84 // True if an attempt has been made to load the database (even if the attempt | |
| 85 // fails), used to avoid continually trying to reinit if the db init fails. | |
| 86 bool init_complete_; | |
| 87 | |
| 88 // The application locale. The locale is needed for some database migrations, | |
| 89 // and must be read on the UI thread. It's cached here so that we can pass it | |
| 90 // to the migration code on the DB thread. | |
| 91 const std::string app_locale_; | |
| 92 | |
| 93 DISALLOW_COPY_AND_ASSIGN(WebDatabaseServiceInternal); | |
| 94 }; | |
| 95 | |
| 96 //////////////////////////////////////////////////////////////////////////////// | |
| 97 // | |
| 98 // WebDatabaseServiceInternal implementation. | |
| 99 // | |
| 100 //////////////////////////////////////////////////////////////////////////////// | |
| 101 | |
| 102 WebDatabaseServiceInternal::WebDatabaseServiceInternal(const FilePath& path) | |
| 103 : db_path_(path), | |
| 104 request_manager_(new WebDataRequestManager()), | |
| 105 init_status_(sql::INIT_FAILURE), | |
| 106 init_complete_(false), | |
| 107 app_locale_(AutofillCountry::ApplicationLocale()) { | |
| 108 } | |
| 109 | |
| 110 void WebDatabaseServiceInternal::InitDatabaseWithCallback( | |
| 111 const WebDatabaseService::InitCallback& callback) { | |
| 112 if (!callback.is_null()) { | |
| 113 callback.Run(LoadDatabaseIfNecessary()); | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 sql::InitStatus WebDatabaseServiceInternal::LoadDatabaseIfNecessary() { | |
| 118 if (init_complete_ || db_path_.empty()) { | |
| 119 return init_status_; | |
| 120 } | |
| 121 init_complete_ = true; | |
| 122 db_.reset(new WebDatabase()); | |
| 123 init_status_ = db_->Init(db_path_, app_locale_); | |
| 124 if (init_status_ != sql::INIT_OK) { | |
| 125 LOG(ERROR) << "Cannot initialize the web database: " << init_status_; | |
| 126 db_.reset(NULL); | |
| 127 return init_status_; | |
| 128 } | |
| 129 | |
| 130 db_->BeginTransaction(); | |
| 131 return init_status_; | |
| 132 } | |
| 133 | |
| 134 void WebDatabaseServiceInternal::ShutdownDatabase(bool should_reinit) { | |
| 135 if (db_.get() && init_status_ == sql::INIT_OK) | |
|
dhollowa
2013/03/15 23:50:31
if(db_ &&...
Cait (Slow)
2013/03/16 21:34:22
Done.
| |
| 136 db_->CommitTransaction(); | |
| 137 db_.reset(NULL); | |
| 138 init_complete_ = !should_reinit; // Setting init_complete_ to true will ensure | |
| 139 // that the init sequence is not re-run. | |
| 140 | |
| 141 init_status_ = sql::INIT_FAILURE; | |
| 142 } | |
| 143 | |
| 144 void WebDatabaseServiceInternal::DBWriteTaskWrapper( | |
| 145 const WebDatabaseService::WriteTask& task, | |
| 146 scoped_ptr<WebDataRequest> request) { | |
| 147 LoadDatabaseIfNecessary(); | |
| 148 if (db_.get() && init_status_ == sql::INIT_OK && !request->IsCancelled()) { | |
|
dhollowa
2013/03/15 23:50:31
if(db_ &&...
Cait (Slow)
2013/03/16 21:34:22
Done.
| |
| 149 WebDatabase::State state = task.Run(db_.get()); | |
| 150 if (state == WebDatabase::COMMIT_NEEDED) | |
| 151 Commit(); | |
| 152 } | |
| 153 request_manager_->RequestCompleted(request.Pass()); | |
| 154 } | |
| 155 | |
| 156 void WebDatabaseServiceInternal::DBReadTaskWrapper( | |
| 157 const WebDatabaseService::ReadTask& task, | |
| 158 scoped_ptr<WebDataRequest> request) { | |
| 159 LoadDatabaseIfNecessary(); | |
| 160 if (db_.get() && init_status_ == sql::INIT_OK && !request->IsCancelled()) { | |
|
dhollowa
2013/03/15 23:50:31
if(db_ &&...
Cait (Slow)
2013/03/16 21:34:22
Done.
| |
| 161 request->SetResult(task.Run(db_.get()).Pass()); | |
| 162 } | |
| 163 request_manager_->RequestCompleted(request.Pass()); | |
| 164 } | |
| 165 | |
| 166 WebDatabaseServiceInternal::~WebDatabaseServiceInternal() { | |
| 167 ShutdownDatabase(false); | |
| 168 } | |
| 169 | |
| 170 void WebDatabaseServiceInternal::Commit() { | |
| 171 if (db_.get() && init_status_ == sql::INIT_OK) { | |
|
dhollowa
2013/03/15 23:50:31
if(db_ &&...
Cait (Slow)
2013/03/16 21:34:22
Done.
| |
| 172 db_->CommitTransaction(); | |
|
dhollowa
2013/03/15 23:50:31
nit: Indent
Cait (Slow)
2013/03/16 21:34:22
Done.
| |
| 173 db_->BeginTransaction(); | |
| 174 } else { | |
| 175 NOTREACHED() << "Commit scheduled after Shutdown()"; | |
| 176 } | |
| 177 } | |
| 178 | |
| 179 //////////////////////////////////////////////////////////////////////////////// | |
| 180 WebDatabaseService::WebDatabaseService(const base::FilePath& path) | |
| 181 : path_(path) { | |
| 182 // WebDatabaseService should be instantiated on UI thread. | |
| 183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 184 // WebDatabaseService requires DB thread if instantiated. | |
| 185 DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::DB)); | |
| 186 } | |
| 187 | |
| 188 WebDatabaseService::~WebDatabaseService() { | |
| 189 } | |
| 190 | |
| 191 void WebDatabaseService::LoadDatabase(const InitCallback& callback) { | |
| 192 if (!wdbs_internal_) | |
| 193 wdbs_internal_ = new WebDatabaseServiceInternal(path_); | |
| 194 | |
| 195 BrowserThread::PostTask( | |
| 196 BrowserThread::DB, | |
| 197 FROM_HERE, | |
| 198 Bind(&WebDatabaseServiceInternal::InitDatabaseWithCallback, | |
| 199 wdbs_internal_, callback)); | |
| 200 } | |
| 201 | |
| 202 void WebDatabaseService::UnloadDatabase() { | |
| 203 if (!wdbs_internal_) | |
| 204 return; | |
| 205 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
| 206 Bind(&WebDatabaseServiceInternal::ShutdownDatabase, | |
| 207 wdbs_internal_, true)); | |
| 208 } | |
| 209 | |
| 210 void WebDatabaseService::ShutdownDatabase() { | |
| 211 if (!wdbs_internal_) | |
| 212 return; | |
| 213 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
| 214 Bind(&WebDatabaseServiceInternal::ShutdownDatabase, | |
| 215 wdbs_internal_, false)); | |
| 216 } | |
| 217 | |
| 218 WebDatabase* WebDatabaseService::GetDatabaseOnDB() const { | |
| 219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 220 if (!wdbs_internal_) | |
| 221 return NULL; | |
| 222 return wdbs_internal_->database(); | |
| 223 } | |
| 224 | |
| 225 void WebDatabaseService::ScheduleDBTask( | |
| 226 const tracked_objects::Location& from_here, | |
|
dhollowa
2013/03/15 23:50:31
nit: Indent
Cait (Slow)
2013/03/16 21:34:22
Done.
| |
| 227 const WriteTask& task) { | |
| 228 if (!wdbs_internal_) { | |
| 229 NOTREACHED() << "Task scheduled after Shutdown()"; | |
| 230 return; | |
| 231 } | |
| 232 | |
| 233 scoped_ptr<WebDataRequest> request( | |
| 234 new WebDataRequest(NULL, wdbs_internal_->request_manager())); | |
| 235 | |
| 236 BrowserThread::PostTask(BrowserThread::DB, from_here, | |
| 237 Bind(&WebDatabaseServiceInternal::DBWriteTaskWrapper, wdbs_internal_, | |
| 238 task, base::Passed(&request))); | |
| 239 } | |
| 240 | |
| 241 WebDataService::Handle WebDatabaseService::ScheduleDBTaskWithResult( | |
| 242 const tracked_objects::Location& from_here, | |
|
dhollowa
2013/03/15 23:50:31
nit: Indent
Cait (Slow)
2013/03/16 21:34:22
Done.
| |
| 243 const ReadTask& task, | |
| 244 WebDataServiceConsumer* consumer) { | |
| 245 DCHECK(consumer); | |
| 246 WebDataService::Handle handle = 0; | |
| 247 | |
| 248 if (!wdbs_internal_) { | |
| 249 NOTREACHED() << "Task scheduled after Shutdown()"; | |
| 250 return handle; | |
| 251 } | |
| 252 | |
| 253 scoped_ptr<WebDataRequest> request( | |
| 254 new WebDataRequest(consumer, wdbs_internal_->request_manager())); | |
| 255 handle = request->GetHandle(); | |
| 256 | |
| 257 BrowserThread::PostTask(BrowserThread::DB, from_here, | |
| 258 Bind(&WebDatabaseServiceInternal::DBReadTaskWrapper, wdbs_internal_, | |
| 259 task, base::Passed(&request))); | |
| 260 | |
| 261 return handle; | |
| 262 } | |
| 263 | |
| 264 void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) { | |
| 265 if (!wdbs_internal_) | |
| 266 return; | |
| 267 wdbs_internal_->request_manager()->CancelRequest(h); | |
| 268 } | |
| OLD | NEW |