OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/webdata/web_database_service.h" | 5 #include "chrome/browser/webdata/web_database_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/memory/scoped_vector.h" |
9 #include "chrome/browser/api/webdata/web_data_results.h" | 10 #include "chrome/browser/api/webdata/web_data_results.h" |
10 #include "chrome/browser/api/webdata/web_data_service_consumer.h" | 11 #include "chrome/browser/api/webdata/web_data_service_consumer.h" |
11 #include "chrome/browser/webdata/autofill_table.h" | |
12 #include "chrome/browser/webdata/keyword_table.h" | |
13 #include "chrome/browser/webdata/logins_table.h" | |
14 #include "chrome/browser/webdata/token_service_table.h" | |
15 #include "chrome/browser/webdata/web_apps_table.h" | |
16 #include "chrome/browser/webdata/web_data_request_manager.h" | 12 #include "chrome/browser/webdata/web_data_request_manager.h" |
17 #include "chrome/browser/webdata/web_data_service.h" | |
18 #include "chrome/browser/webdata/web_intents_table.h" | |
19 // TODO(caitkp): Remove this autofill dependency. | 13 // TODO(caitkp): Remove this autofill dependency. |
20 #include "components/autofill/browser/autofill_country.h" | 14 #include "components/autofill/browser/autofill_country.h" |
21 | 15 |
22 using base::Bind; | 16 using base::Bind; |
23 using base::FilePath; | 17 using base::FilePath; |
24 using content::BrowserThread; | 18 using content::BrowserThread; |
25 | 19 |
26 | 20 |
27 //////////////////////////////////////////////////////////////////////////////// | 21 //////////////////////////////////////////////////////////////////////////////// |
28 // | 22 // |
29 // WebDataServiceBackend implementation. | 23 // WebDataServiceBackend implementation. |
30 // | 24 // |
31 //////////////////////////////////////////////////////////////////////////////// | 25 //////////////////////////////////////////////////////////////////////////////// |
32 | 26 |
33 // Refcounted to allow asynchronous destruction on the DB thread. | 27 // Refcounted to allow asynchronous destruction on the DB thread. |
34 class WebDataServiceBackend | 28 class WebDataServiceBackend |
35 : public base::RefCountedThreadSafe<WebDataServiceBackend, | 29 : public base::RefCountedThreadSafe<WebDataServiceBackend, |
36 BrowserThread::DeleteOnDBThread> { | 30 BrowserThread::DeleteOnDBThread> { |
37 public: | 31 public: |
38 explicit WebDataServiceBackend(const FilePath& path); | 32 explicit WebDataServiceBackend(const FilePath& path); |
39 | 33 |
| 34 // Must call only before InitDatabaseWithCallback. |
| 35 void AddTable(scoped_ptr<WebDatabaseTable> table); |
| 36 |
40 // Initializes the database and notifies caller via callback when complete. | 37 // Initializes the database and notifies caller via callback when complete. |
41 // Callback is called synchronously. | 38 // Callback is called synchronously. |
42 void InitDatabaseWithCallback( | 39 void InitDatabaseWithCallback( |
43 const WebDatabaseService::InitCallback& callback); | 40 const WebDatabaseService::InitCallback& callback); |
44 | 41 |
45 // Opens the database file from the profile path if an init has not yet been | 42 // Opens the database file from the profile path if an init has not yet been |
46 // attempted. Separated from the constructor to ease construction/destruction | 43 // attempted. Separated from the constructor to ease construction/destruction |
47 // of this object on one thread but database access on the DB thread. Returns | 44 // of this object on one thread but database access on the DB thread. Returns |
48 // the status of the database. | 45 // the status of the database. |
49 sql::InitStatus LoadDatabaseIfNecessary(); | 46 sql::InitStatus LoadDatabaseIfNecessary(); |
(...skipping 21 matching lines...) Expand all Loading... |
71 friend class base::DeleteHelper<WebDataServiceBackend>; | 68 friend class base::DeleteHelper<WebDataServiceBackend>; |
72 | 69 |
73 virtual ~WebDataServiceBackend(); | 70 virtual ~WebDataServiceBackend(); |
74 | 71 |
75 // Commit the current transaction. | 72 // Commit the current transaction. |
76 void Commit(); | 73 void Commit(); |
77 | 74 |
78 // Path to database file. | 75 // Path to database file. |
79 FilePath db_path_; | 76 FilePath db_path_; |
80 | 77 |
81 scoped_ptr<AutofillTable> autofill_table_; | 78 // The tables that participate in managing the database. These are |
82 scoped_ptr<KeywordTable> keyword_table_; | 79 // owned here but other than that this class does nothing with |
83 scoped_ptr<LoginsTable> logins_table_; | 80 // them. Their initialization is in whatever factory creates |
84 scoped_ptr<TokenServiceTable> token_service_table_; | 81 // WebDatabaseService, and lookup by type is provided by the |
85 scoped_ptr<WebAppsTable> web_apps_table_; | 82 // WebDatabase class. The tables need to be owned by this refcounted |
86 scoped_ptr<WebIntentsTable> web_intents_table_; | 83 // object, or they themselves would need to be refcounted. Owning |
| 84 // them here rather than having WebDatabase own them makes for |
| 85 // easier unit testing of WebDatabase. |
| 86 ScopedVector<WebDatabaseTable> tables_; |
87 | 87 |
88 scoped_ptr<WebDatabase> db_; | 88 scoped_ptr<WebDatabase> db_; |
89 | 89 |
90 // Keeps track of all pending requests made to the db. | 90 // Keeps track of all pending requests made to the db. |
91 scoped_refptr<WebDataRequestManager> request_manager_; | 91 scoped_refptr<WebDataRequestManager> request_manager_; |
92 | 92 |
93 // State of database initialization. Used to prevent the executing of tasks | 93 // State of database initialization. Used to prevent the executing of tasks |
94 // before the db is ready. | 94 // before the db is ready. |
95 sql::InitStatus init_status_; | 95 sql::InitStatus init_status_; |
96 | 96 |
(...skipping 10 matching lines...) Expand all Loading... |
107 }; | 107 }; |
108 | 108 |
109 WebDataServiceBackend::WebDataServiceBackend(const FilePath& path) | 109 WebDataServiceBackend::WebDataServiceBackend(const FilePath& path) |
110 : db_path_(path), | 110 : db_path_(path), |
111 request_manager_(new WebDataRequestManager()), | 111 request_manager_(new WebDataRequestManager()), |
112 init_status_(sql::INIT_FAILURE), | 112 init_status_(sql::INIT_FAILURE), |
113 init_complete_(false), | 113 init_complete_(false), |
114 app_locale_(AutofillCountry::ApplicationLocale()) { | 114 app_locale_(AutofillCountry::ApplicationLocale()) { |
115 } | 115 } |
116 | 116 |
| 117 void WebDataServiceBackend::AddTable(scoped_ptr<WebDatabaseTable> table) { |
| 118 DCHECK(!db_.get()); |
| 119 tables_.push_back(table.release()); |
| 120 } |
| 121 |
117 void WebDataServiceBackend::InitDatabaseWithCallback( | 122 void WebDataServiceBackend::InitDatabaseWithCallback( |
118 const WebDatabaseService::InitCallback& callback) { | 123 const WebDatabaseService::InitCallback& callback) { |
119 if (!callback.is_null()) { | 124 if (!callback.is_null()) { |
120 callback.Run(LoadDatabaseIfNecessary()); | 125 callback.Run(LoadDatabaseIfNecessary()); |
121 } | 126 } |
122 } | 127 } |
123 | 128 |
124 sql::InitStatus WebDataServiceBackend::LoadDatabaseIfNecessary() { | 129 sql::InitStatus WebDataServiceBackend::LoadDatabaseIfNecessary() { |
125 if (init_complete_ || db_path_.empty()) { | 130 if (init_complete_ || db_path_.empty()) { |
126 return init_status_; | 131 return init_status_; |
127 } | 132 } |
128 init_complete_ = true; | 133 init_complete_ = true; |
129 db_.reset(new WebDatabase()); | 134 db_.reset(new WebDatabase()); |
130 | 135 |
131 // All tables objects that participate in managing the database must | 136 for (ScopedVector<WebDatabaseTable>::iterator it = tables_.begin(); |
132 // be added here. | 137 it != tables_.end(); |
133 autofill_table_.reset(new AutofillTable()); | 138 ++it) { |
134 db_->AddTable(autofill_table_.get()); | 139 db_->AddTable(*it); |
135 | 140 } |
136 keyword_table_.reset(new KeywordTable()); | |
137 db_->AddTable(keyword_table_.get()); | |
138 | |
139 // TODO(mdm): We only really need the LoginsTable on Windows for IE7 password | |
140 // access, but for now, we still create it on all platforms since it deletes | |
141 // the old logins table. We can remove this after a while, e.g. in M22 or so. | |
142 logins_table_.reset(new LoginsTable()); | |
143 db_->AddTable(logins_table_.get()); | |
144 | |
145 token_service_table_.reset(new TokenServiceTable()); | |
146 db_->AddTable(token_service_table_.get()); | |
147 | |
148 web_apps_table_.reset(new WebAppsTable()); | |
149 db_->AddTable(web_apps_table_.get()); | |
150 | |
151 // TODO(thakis): Add a migration to delete the SQL table used by | |
152 // WebIntentsTable, then remove this. | |
153 web_intents_table_.reset(new WebIntentsTable()); | |
154 db_->AddTable(web_intents_table_.get()); | |
155 | 141 |
156 init_status_ = db_->Init(db_path_, app_locale_); | 142 init_status_ = db_->Init(db_path_, app_locale_); |
157 if (init_status_ != sql::INIT_OK) { | 143 if (init_status_ != sql::INIT_OK) { |
158 LOG(ERROR) << "Cannot initialize the web database: " << init_status_; | 144 LOG(ERROR) << "Cannot initialize the web database: " << init_status_; |
159 db_.reset(NULL); | 145 db_.reset(NULL); |
160 return init_status_; | 146 return init_status_; |
161 } | 147 } |
162 | 148 |
163 db_->BeginTransaction(); | 149 db_->BeginTransaction(); |
164 return init_status_; | 150 return init_status_; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 : path_(path) { | 200 : path_(path) { |
215 // WebDatabaseService should be instantiated on UI thread. | 201 // WebDatabaseService should be instantiated on UI thread. |
216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
217 // WebDatabaseService requires DB thread if instantiated. | 203 // WebDatabaseService requires DB thread if instantiated. |
218 DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::DB)); | 204 DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::DB)); |
219 } | 205 } |
220 | 206 |
221 WebDatabaseService::~WebDatabaseService() { | 207 WebDatabaseService::~WebDatabaseService() { |
222 } | 208 } |
223 | 209 |
| 210 void WebDatabaseService::AddTable(scoped_ptr<WebDatabaseTable> table) { |
| 211 if (!wds_backend_) { |
| 212 wds_backend_ = new WebDataServiceBackend(path_); |
| 213 } |
| 214 wds_backend_->AddTable(table.Pass()); |
| 215 } |
| 216 |
224 void WebDatabaseService::LoadDatabase(const InitCallback& callback) { | 217 void WebDatabaseService::LoadDatabase(const InitCallback& callback) { |
225 if (!wds_backend_) | 218 DCHECK(wds_backend_); |
226 wds_backend_ = new WebDataServiceBackend(path_); | |
227 | 219 |
228 BrowserThread::PostTask( | 220 BrowserThread::PostTask( |
229 BrowserThread::DB, | 221 BrowserThread::DB, |
230 FROM_HERE, | 222 FROM_HERE, |
231 Bind(&WebDataServiceBackend::InitDatabaseWithCallback, | 223 Bind(&WebDataServiceBackend::InitDatabaseWithCallback, |
232 wds_backend_, callback)); | 224 wds_backend_, callback)); |
233 } | 225 } |
234 | 226 |
235 void WebDatabaseService::UnloadDatabase() { | 227 void WebDatabaseService::UnloadDatabase() { |
236 if (!wds_backend_) | 228 if (!wds_backend_) |
(...skipping 27 matching lines...) Expand all Loading... |
264 } | 256 } |
265 | 257 |
266 scoped_ptr<WebDataRequest> request( | 258 scoped_ptr<WebDataRequest> request( |
267 new WebDataRequest(NULL, wds_backend_->request_manager())); | 259 new WebDataRequest(NULL, wds_backend_->request_manager())); |
268 | 260 |
269 BrowserThread::PostTask(BrowserThread::DB, from_here, | 261 BrowserThread::PostTask(BrowserThread::DB, from_here, |
270 Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_, | 262 Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_, |
271 task, base::Passed(&request))); | 263 task, base::Passed(&request))); |
272 } | 264 } |
273 | 265 |
274 WebDataService::Handle WebDatabaseService::ScheduleDBTaskWithResult( | 266 WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult( |
275 const tracked_objects::Location& from_here, | 267 const tracked_objects::Location& from_here, |
276 const ReadTask& task, | 268 const ReadTask& task, |
277 WebDataServiceConsumer* consumer) { | 269 WebDataServiceConsumer* consumer) { |
278 DCHECK(consumer); | 270 DCHECK(consumer); |
279 WebDataService::Handle handle = 0; | 271 WebDataServiceBase::Handle handle = 0; |
280 | 272 |
281 if (!wds_backend_) { | 273 if (!wds_backend_) { |
282 NOTREACHED() << "Task scheduled after Shutdown()"; | 274 NOTREACHED() << "Task scheduled after Shutdown()"; |
283 return handle; | 275 return handle; |
284 } | 276 } |
285 | 277 |
286 scoped_ptr<WebDataRequest> request( | 278 scoped_ptr<WebDataRequest> request( |
287 new WebDataRequest(consumer, wds_backend_->request_manager())); | 279 new WebDataRequest(consumer, wds_backend_->request_manager())); |
288 handle = request->GetHandle(); | 280 handle = request->GetHandle(); |
289 | 281 |
290 BrowserThread::PostTask(BrowserThread::DB, from_here, | 282 BrowserThread::PostTask(BrowserThread::DB, from_here, |
291 Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_, | 283 Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_, |
292 task, base::Passed(&request))); | 284 task, base::Passed(&request))); |
293 | 285 |
294 return handle; | 286 return handle; |
295 } | 287 } |
296 | 288 |
297 void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) { | 289 void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) { |
298 if (!wds_backend_) | 290 if (!wds_backend_) |
299 return; | 291 return; |
300 wds_backend_->request_manager()->CancelRequest(h); | 292 wds_backend_->request_manager()->CancelRequest(h); |
301 } | 293 } |
OLD | NEW |