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 | |
dhollowa
2013/03/15 18:56:21
nit: Remove empty line.
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
33 explicit WebDatabaseServiceInternal(const FilePath& path); | |
34 | |
35 // Initializes the database and notifies caller via callback when complete. | |
dhollowa
2013/03/15 18:56:21
Please mention that callback is called synchronous
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
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 | |
dhollowa
2013/03/15 18:56:21
Remove comma in "path, if".
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
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_; } | |
dhollowa
2013/03/15 18:56:21
} on new line
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
59 | |
60 WebDatabase* database() {return db_.get();} | |
dhollowa
2013/03/15 18:56:21
nit: space after { and before }
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
61 | |
62 private: | |
63 friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>; | |
64 friend class base::DeleteHelper<WebDatabaseServiceInternal>; | |
65 | |
66 virtual ~WebDatabaseServiceInternal(); | |
67 | |
68 // Commit the current transaction. | |
69 void Commit(); | |
70 | |
71 // Path to database file. | |
72 FilePath db_path_; | |
73 | |
74 scoped_ptr<WebDatabase> db_; | |
75 | |
76 // Keeps track of all pending requests made to the db. | |
77 scoped_refptr<WebDataRequestManager> request_manager_; | |
78 | |
79 // State of database initialization. Used to prevent the executing of tasks | |
80 // before the db is ready. | |
81 sql::InitStatus init_status_; | |
82 | |
83 // True if an attempt has been made to load the database (even if the attempt | |
84 // fails), used to avoid continually trying to reinit if the db init fails. | |
85 bool init_complete_; | |
86 | |
87 // The application locale. The locale is needed for some database migrations, | |
88 // and must be read on the UI thread. It's cached here so that we can pass it | |
89 // to the migration code on the DB thread. | |
90 const std::string app_locale_; | |
91 | |
92 DISALLOW_COPY_AND_ASSIGN(WebDatabaseServiceInternal); | |
93 }; | |
94 | |
95 //////////////////////////////////////////////////////////////////////////////// | |
96 // | |
97 // WebDatabaseServiceInternal implementation. | |
98 // | |
99 //////////////////////////////////////////////////////////////////////////////// | |
100 | |
101 WebDatabaseServiceInternal::WebDatabaseServiceInternal(const FilePath& path) | |
102 : db_path_(path), | |
103 request_manager_(new WebDataRequestManager()), | |
104 init_status_(sql::INIT_FAILURE), | |
105 init_complete_(false), | |
106 app_locale_(AutofillCountry::ApplicationLocale()) { | |
107 db_.reset(NULL); | |
dhollowa
2013/03/15 18:56:21
Not needed.
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
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) | |
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()) { | |
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()) { | |
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) { | |
172 db_->CommitTransaction(); | |
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 wdbs_internal_ = NULL; | |
dhollowa
2013/03/15 18:56:21
Not needed.
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
190 } | |
191 | |
192 void WebDatabaseService::LoadDatabase(const InitCallback& callback) { | |
193 if (!wdbs_internal_) { | |
dhollowa
2013/03/15 18:56:21
nit: No need for {}
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
194 wdbs_internal_ = new WebDatabaseServiceInternal(path_); | |
195 } | |
196 BrowserThread::PostTask( | |
197 BrowserThread::DB, | |
198 FROM_HERE, | |
199 Bind(&WebDatabaseServiceInternal::InitDatabaseWithCallback, | |
200 wdbs_internal_, callback)); | |
201 } | |
202 | |
203 void WebDatabaseService::UnloadDatabase() { | |
204 if (wdbs_internal_) { | |
dhollowa
2013/03/15 18:56:21
Please change to the form:
if (!wdbs_internal_)
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
205 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
206 Bind(&WebDatabaseServiceInternal::ShutdownDatabase, | |
207 wdbs_internal_, true)); | |
208 } | |
209 } | |
210 | |
211 void WebDatabaseService::ShutdownDatabase() { | |
212 if (wdbs_internal_) { | |
dhollowa
2013/03/15 18:56:21
Please change to the form:
if (!wdbs_internal_)
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
213 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
214 Bind(&WebDatabaseServiceInternal::ShutdownDatabase, | |
215 wdbs_internal_, false)); | |
216 } | |
217 } | |
218 | |
219 WebDatabase* WebDatabaseService::GetDatabase() const { | |
dhollowa
2013/03/15 18:56:21
Consider changing these exceptional methods to *On
Cait (Slow)
2013/03/15 20:43:59
Done. Changed WebDatabaseService method names. Wil
| |
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
221 if (wdbs_internal_) | |
dhollowa
2013/03/15 18:56:21
Please change to the form:
if (!wdbs_internal_)
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
222 return wdbs_internal_->database(); | |
223 return NULL; | |
224 } | |
225 | |
226 void WebDatabaseService::ScheduleDBTask( | |
227 const tracked_objects::Location& from_here, | |
228 const WriteTask& task) { | |
229 if (!wdbs_internal_) { | |
230 NOTREACHED() << "Task scheduled after Shutdown()"; | |
231 return; | |
232 } | |
233 | |
234 scoped_ptr<WebDataRequest> request( | |
235 new WebDataRequest(NULL, wdbs_internal_->request_manager())); | |
236 | |
237 BrowserThread::PostTask(BrowserThread::DB, from_here, | |
238 Bind(&WebDatabaseServiceInternal::DBWriteTaskWrapper, wdbs_internal_, | |
239 task, base::Passed(&request))); | |
240 } | |
241 | |
242 WebDataService::Handle WebDatabaseService::ScheduleDBTaskWithResult( | |
243 const tracked_objects::Location& from_here, | |
244 const ReadTask& task, | |
245 WebDataServiceConsumer* consumer) { | |
246 DCHECK(consumer); | |
247 WebDataService::Handle handle = 0; | |
248 | |
249 if (!wdbs_internal_) { | |
250 NOTREACHED() << "Task scheduled after Shutdown()"; | |
251 return handle; | |
252 } | |
253 | |
254 scoped_ptr<WebDataRequest> request( | |
255 new WebDataRequest(consumer, wdbs_internal_->request_manager())); | |
256 handle = request->GetHandle(); | |
257 | |
258 BrowserThread::PostTask(BrowserThread::DB, from_here, | |
259 Bind(&WebDatabaseServiceInternal::DBReadTaskWrapper, wdbs_internal_, | |
260 task, base::Passed(&request))); | |
261 | |
262 return handle; | |
263 } | |
264 | |
265 void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) { | |
266 if (wdbs_internal_) | |
dhollowa
2013/03/15 18:56:21
Please change to the form:
if (!wdbs_internal_)
Cait (Slow)
2013/03/15 20:43:59
Done.
| |
267 wdbs_internal_->request_manager()->CancelRequest(h); | |
268 } | |
OLD | NEW |