- add sources.
[platform/framework/web/crosswalk.git] / src / components / webdata / common / web_database_service.cc
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_database_service.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_data_results.h"
11 #include "components/webdata/common/web_data_service_backend.h"
12 #include "components/webdata/common/web_data_service_consumer.h"
13
14 using base::Bind;
15 using base::FilePath;
16
17 // Receives messages from the backend on the DB thread, posts them to
18 // WebDatabaseService on the UI thread.
19 class WebDatabaseService::BackendDelegate :
20     public WebDataServiceBackend::Delegate {
21  public:
22   BackendDelegate(
23       const base::WeakPtr<WebDatabaseService>& web_database_service)
24       : web_database_service_(web_database_service),
25         callback_thread_(base::MessageLoopProxy::current()) {
26   }
27
28   virtual void DBLoaded(sql::InitStatus status) OVERRIDE {
29     callback_thread_->PostTask(
30         FROM_HERE,
31         base::Bind(&WebDatabaseService::OnDatabaseLoadDone,
32                    web_database_service_,
33                    status));
34   }
35  private:
36   const base::WeakPtr<WebDatabaseService> web_database_service_;
37   scoped_refptr<base::MessageLoopProxy> callback_thread_;
38 };
39
40 WebDatabaseService::WebDatabaseService(
41     const base::FilePath& path,
42     const scoped_refptr<base::MessageLoopProxy>& ui_thread,
43     const scoped_refptr<base::MessageLoopProxy>& db_thread)
44     : base::RefCountedDeleteOnMessageLoop<WebDatabaseService>(ui_thread),
45       path_(path),
46       weak_ptr_factory_(this),
47       db_loaded_(false),
48       db_thread_(db_thread) {
49   // WebDatabaseService should be instantiated on UI thread.
50   DCHECK(ui_thread->BelongsToCurrentThread());
51   // WebDatabaseService requires DB thread if instantiated.
52   DCHECK(db_thread.get());
53 }
54
55 WebDatabaseService::~WebDatabaseService() {
56 }
57
58 void WebDatabaseService::AddTable(scoped_ptr<WebDatabaseTable> table) {
59   if (!wds_backend_.get()) {
60     wds_backend_ = new WebDataServiceBackend(
61         path_, new BackendDelegate(weak_ptr_factory_.GetWeakPtr()),
62         db_thread_);
63   }
64   wds_backend_->AddTable(table.Pass());
65 }
66
67 void WebDatabaseService::LoadDatabase() {
68   DCHECK(wds_backend_.get());
69
70   db_thread_->PostTask(
71       FROM_HERE,
72       Bind(&WebDataServiceBackend::InitDatabase, wds_backend_));
73 }
74
75 void WebDatabaseService::UnloadDatabase() {
76   db_loaded_ = false;
77   if (!wds_backend_.get())
78     return;
79   db_thread_->PostTask(FROM_HERE,
80       Bind(&WebDataServiceBackend::ShutdownDatabase,
81            wds_backend_, true));
82 }
83
84 void WebDatabaseService::ShutdownDatabase() {
85   db_loaded_ = false;
86   weak_ptr_factory_.InvalidateWeakPtrs();
87   loaded_callbacks_.clear();
88   error_callbacks_.clear();
89   if (!wds_backend_.get())
90     return;
91   db_thread_->PostTask(FROM_HERE,
92       Bind(&WebDataServiceBackend::ShutdownDatabase,
93            wds_backend_, false));
94 }
95
96 WebDatabase* WebDatabaseService::GetDatabaseOnDB() const {
97   DCHECK(db_thread_->BelongsToCurrentThread());
98   if (!wds_backend_.get())
99     return NULL;
100   return wds_backend_->database();
101 }
102
103 scoped_refptr<WebDataServiceBackend> WebDatabaseService::GetBackend() const {
104   return wds_backend_;
105 }
106
107 void WebDatabaseService::ScheduleDBTask(
108     const tracked_objects::Location& from_here,
109     const WriteTask& task) {
110   if (!wds_backend_.get()) {
111     NOTREACHED() << "Task scheduled after Shutdown()";
112     return;
113   }
114
115   scoped_ptr<WebDataRequest> request(
116       new WebDataRequest(NULL, wds_backend_->request_manager().get()));
117
118   db_thread_->PostTask(from_here,
119       Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_,
120            task, base::Passed(&request)));
121 }
122
123 WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult(
124     const tracked_objects::Location& from_here,
125     const ReadTask& task,
126     WebDataServiceConsumer* consumer) {
127   DCHECK(consumer);
128   WebDataServiceBase::Handle handle = 0;
129
130   if (!wds_backend_.get()) {
131     NOTREACHED() << "Task scheduled after Shutdown()";
132     return handle;
133   }
134
135   scoped_ptr<WebDataRequest> request(
136       new WebDataRequest(consumer, wds_backend_->request_manager().get()));
137   handle = request->GetHandle();
138
139   db_thread_->PostTask(from_here,
140       Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_,
141            task, base::Passed(&request)));
142
143   return handle;
144 }
145
146 void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) {
147   if (!wds_backend_.get())
148     return;
149   wds_backend_->request_manager()->CancelRequest(h);
150 }
151
152 void WebDatabaseService::RegisterDBLoadedCallback(
153     const DBLoadedCallback& callback) {
154   loaded_callbacks_.push_back(callback);
155 }
156
157 void WebDatabaseService::RegisterDBErrorCallback(
158     const DBLoadErrorCallback& callback) {
159   error_callbacks_.push_back(callback);
160 }
161
162 void WebDatabaseService::OnDatabaseLoadDone(sql::InitStatus status) {
163   if (status == sql::INIT_OK) {
164     db_loaded_ = true;
165
166     for (size_t i = 0; i < loaded_callbacks_.size(); i++) {
167       if (!loaded_callbacks_[i].is_null())
168         loaded_callbacks_[i].Run();
169     }
170
171     loaded_callbacks_.clear();
172   } else {
173     // Notify that the database load failed.
174     for (size_t i = 0; i < error_callbacks_.size(); i++) {
175       if (!error_callbacks_[i].is_null())
176         error_callbacks_[i].Run(status);
177     }
178
179     error_callbacks_.clear();
180   }
181 }