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 |