diff options
Diffstat (limited to 'chromium/components/webdata/common/web_database_service.cc')
| -rw-r--r-- | chromium/components/webdata/common/web_database_service.cc | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/chromium/components/webdata/common/web_database_service.cc b/chromium/components/webdata/common/web_database_service.cc new file mode 100644 index 00000000000..11eb30b8bf1 --- /dev/null +++ b/chromium/components/webdata/common/web_database_service.cc @@ -0,0 +1,181 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/webdata/common/web_database_service.h" + +#include "base/bind.h" +#include "base/location.h" +#include "components/webdata/common/web_data_request_manager.h" +#include "components/webdata/common/web_data_results.h" +#include "components/webdata/common/web_data_service_backend.h" +#include "components/webdata/common/web_data_service_consumer.h" + +using base::Bind; +using base::FilePath; + +// Receives messages from the backend on the DB thread, posts them to +// WebDatabaseService on the UI thread. +class WebDatabaseService::BackendDelegate : + public WebDataServiceBackend::Delegate { + public: + BackendDelegate( + const base::WeakPtr<WebDatabaseService>& web_database_service) + : web_database_service_(web_database_service), + callback_thread_(base::MessageLoopProxy::current()) { + } + + virtual void DBLoaded(sql::InitStatus status) OVERRIDE { + callback_thread_->PostTask( + FROM_HERE, + base::Bind(&WebDatabaseService::OnDatabaseLoadDone, + web_database_service_, + status)); + } + private: + const base::WeakPtr<WebDatabaseService> web_database_service_; + scoped_refptr<base::MessageLoopProxy> callback_thread_; +}; + +WebDatabaseService::WebDatabaseService( + const base::FilePath& path, + const scoped_refptr<base::MessageLoopProxy>& ui_thread, + const scoped_refptr<base::MessageLoopProxy>& db_thread) + : base::RefCountedDeleteOnMessageLoop<WebDatabaseService>(ui_thread), + path_(path), + weak_ptr_factory_(this), + db_loaded_(false), + db_thread_(db_thread) { + // WebDatabaseService should be instantiated on UI thread. + DCHECK(ui_thread->BelongsToCurrentThread()); + // WebDatabaseService requires DB thread if instantiated. + DCHECK(db_thread.get()); +} + +WebDatabaseService::~WebDatabaseService() { +} + +void WebDatabaseService::AddTable(scoped_ptr<WebDatabaseTable> table) { + if (!wds_backend_.get()) { + wds_backend_ = new WebDataServiceBackend( + path_, new BackendDelegate(weak_ptr_factory_.GetWeakPtr()), + db_thread_); + } + wds_backend_->AddTable(table.Pass()); +} + +void WebDatabaseService::LoadDatabase() { + DCHECK(wds_backend_.get()); + + db_thread_->PostTask( + FROM_HERE, + Bind(&WebDataServiceBackend::InitDatabase, wds_backend_)); +} + +void WebDatabaseService::UnloadDatabase() { + db_loaded_ = false; + if (!wds_backend_.get()) + return; + db_thread_->PostTask(FROM_HERE, + Bind(&WebDataServiceBackend::ShutdownDatabase, + wds_backend_, true)); +} + +void WebDatabaseService::ShutdownDatabase() { + db_loaded_ = false; + weak_ptr_factory_.InvalidateWeakPtrs(); + loaded_callbacks_.clear(); + error_callbacks_.clear(); + if (!wds_backend_.get()) + return; + db_thread_->PostTask(FROM_HERE, + Bind(&WebDataServiceBackend::ShutdownDatabase, + wds_backend_, false)); +} + +WebDatabase* WebDatabaseService::GetDatabaseOnDB() const { + DCHECK(db_thread_->BelongsToCurrentThread()); + if (!wds_backend_.get()) + return NULL; + return wds_backend_->database(); +} + +scoped_refptr<WebDataServiceBackend> WebDatabaseService::GetBackend() const { + return wds_backend_; +} + +void WebDatabaseService::ScheduleDBTask( + const tracked_objects::Location& from_here, + const WriteTask& task) { + if (!wds_backend_.get()) { + NOTREACHED() << "Task scheduled after Shutdown()"; + return; + } + + scoped_ptr<WebDataRequest> request( + new WebDataRequest(NULL, wds_backend_->request_manager().get())); + + db_thread_->PostTask(from_here, + Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_, + task, base::Passed(&request))); +} + +WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult( + const tracked_objects::Location& from_here, + const ReadTask& task, + WebDataServiceConsumer* consumer) { + DCHECK(consumer); + WebDataServiceBase::Handle handle = 0; + + if (!wds_backend_.get()) { + NOTREACHED() << "Task scheduled after Shutdown()"; + return handle; + } + + scoped_ptr<WebDataRequest> request( + new WebDataRequest(consumer, wds_backend_->request_manager().get())); + handle = request->GetHandle(); + + db_thread_->PostTask(from_here, + Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_, + task, base::Passed(&request))); + + return handle; +} + +void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) { + if (!wds_backend_.get()) + return; + wds_backend_->request_manager()->CancelRequest(h); +} + +void WebDatabaseService::RegisterDBLoadedCallback( + const DBLoadedCallback& callback) { + loaded_callbacks_.push_back(callback); +} + +void WebDatabaseService::RegisterDBErrorCallback( + const DBLoadErrorCallback& callback) { + error_callbacks_.push_back(callback); +} + +void WebDatabaseService::OnDatabaseLoadDone(sql::InitStatus status) { + if (status == sql::INIT_OK) { + db_loaded_ = true; + + for (size_t i = 0; i < loaded_callbacks_.size(); i++) { + if (!loaded_callbacks_[i].is_null()) + loaded_callbacks_[i].Run(); + } + + loaded_callbacks_.clear(); + } else { + // Notify that the database load failed. + for (size_t i = 0; i < error_callbacks_.size(); i++) { + if (!error_callbacks_[i].is_null()) + error_callbacks_[i].Run(status); + } + + error_callbacks_.clear(); + } +} |
