OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/autofill/browser/webdata/autofill_webdata_backend_impl.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/scoped_vector.h" | |
9 #include "base/stl_util.h" | |
10 #include "components/autofill/browser/autofill_country.h" | |
11 #include "components/autofill/browser/autofill_profile.h" | |
12 #include "components/autofill/browser/credit_card.h" | |
13 #include "components/autofill/browser/webdata/autofill_change.h" | |
14 #include "components/autofill/browser/webdata/autofill_entry.h" | |
15 #include "components/autofill/browser/webdata/autofill_table.h" | |
16 #include "components/autofill/browser/webdata/autofill_webdata_service_observer.
h" | |
17 #include "components/autofill/core/common/form_field_data.h" | |
18 #include "components/webdata/common/web_data_service_backend.h" | |
19 | |
20 using base::Bind; | |
21 using base::Time; | |
22 using content::BrowserThread; | |
23 | |
24 namespace autofill { | |
25 | |
26 AutofillWebDataBackendImpl::AutofillWebDataBackendImpl( | |
27 scoped_refptr<WebDataServiceBackend> web_database_backend, | |
28 const base::Closure& on_changed_callback) | |
29 : web_database_backend_(web_database_backend), | |
30 on_changed_callback_(on_changed_callback) { | |
31 } | |
32 | |
33 void AutofillWebDataBackendImpl::AddObserver( | |
34 AutofillWebDataServiceObserverOnDBThread* observer) { | |
35 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
36 db_observer_list_.AddObserver(observer); | |
37 } | |
38 | |
39 void AutofillWebDataBackendImpl::RemoveObserver( | |
40 AutofillWebDataServiceObserverOnDBThread* observer) { | |
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
42 db_observer_list_.RemoveObserver(observer); | |
43 } | |
44 | |
45 AutofillWebDataBackendImpl::~AutofillWebDataBackendImpl() { | |
46 DCHECK(!user_data_.get()); // Forgot to call ResetUserData? | |
47 } | |
48 | |
49 WebDatabase* AutofillWebDataBackendImpl::GetDatabase() { | |
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
51 return web_database_backend_->database(); | |
52 } | |
53 | |
54 void AutofillWebDataBackendImpl::RemoveExpiredFormElements() { | |
55 web_database_backend_->ExecuteWriteTask( | |
56 Bind(&AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl, | |
57 this)); | |
58 } | |
59 | |
60 void AutofillWebDataBackendImpl::NotifyOfMultipleAutofillChanges() { | |
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
62 BrowserThread::PostTask(BrowserThread::UI, | |
63 FROM_HERE, | |
64 on_changed_callback_); | |
65 } | |
66 | |
67 base::SupportsUserData* AutofillWebDataBackendImpl::GetDBUserData() { | |
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
69 if (!user_data_) | |
70 user_data_.reset(new SupportsUserDataAggregatable()); | |
71 return user_data_.get(); | |
72 } | |
73 | |
74 void AutofillWebDataBackendImpl::ResetUserData() { | |
75 user_data_.reset(); | |
76 } | |
77 | |
78 WebDatabase::State AutofillWebDataBackendImpl::AddFormElements( | |
79 const std::vector<FormFieldData>& fields, WebDatabase* db) { | |
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
81 AutofillChangeList changes; | |
82 if (!AutofillTable::FromWebDatabase(db)->AddFormFieldValues( | |
83 fields, &changes)) { | |
84 NOTREACHED(); | |
85 return WebDatabase::COMMIT_NOT_NEEDED; | |
86 } | |
87 | |
88 // Post the notifications including the list of affected keys. | |
89 // This is sent here so that work resulting from this notification will be | |
90 // done on the DB thread, and not the UI thread. | |
91 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
92 db_observer_list_, | |
93 AutofillEntriesChanged(changes)); | |
94 | |
95 return WebDatabase::COMMIT_NEEDED; | |
96 } | |
97 | |
98 scoped_ptr<WDTypedResult> | |
99 AutofillWebDataBackendImpl::GetFormValuesForElementName( | |
100 const base::string16& name, const base::string16& prefix, int limit, | |
101 WebDatabase* db) { | |
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
103 std::vector<base::string16> values; | |
104 AutofillTable::FromWebDatabase(db)->GetFormValuesForElementName( | |
105 name, prefix, &values, limit); | |
106 return scoped_ptr<WDTypedResult>( | |
107 new WDResult<std::vector<base::string16> >(AUTOFILL_VALUE_RESULT, | |
108 values)); | |
109 } | |
110 | |
111 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::HasFormElements( | |
112 WebDatabase* db) { | |
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
114 bool value = AutofillTable::FromWebDatabase(db)->HasFormElements(); | |
115 return scoped_ptr<WDTypedResult>( | |
116 new WDResult<bool>(AUTOFILL_VALUE_RESULT, value)); | |
117 } | |
118 | |
119 WebDatabase::State AutofillWebDataBackendImpl::RemoveFormElementsAddedBetween( | |
120 const base::Time& delete_begin, | |
121 const base::Time& delete_end, | |
122 WebDatabase* db) { | |
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
124 AutofillChangeList changes; | |
125 | |
126 if (AutofillTable::FromWebDatabase(db)->RemoveFormElementsAddedBetween( | |
127 delete_begin, delete_end, &changes)) { | |
128 if (!changes.empty()) { | |
129 // Post the notifications including the list of affected keys. | |
130 // This is sent here so that work resulting from this notification | |
131 // will be done on the DB thread, and not the UI thread. | |
132 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
133 db_observer_list_, | |
134 AutofillEntriesChanged(changes)); | |
135 } | |
136 return WebDatabase::COMMIT_NEEDED; | |
137 } | |
138 return WebDatabase::COMMIT_NOT_NEEDED; | |
139 } | |
140 | |
141 WebDatabase::State AutofillWebDataBackendImpl::RemoveFormValueForElementName( | |
142 const base::string16& name, const base::string16& value, WebDatabase* db) { | |
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
144 | |
145 if (AutofillTable::FromWebDatabase(db)->RemoveFormElement(name, value)) { | |
146 AutofillChangeList changes; | |
147 changes.push_back( | |
148 AutofillChange(AutofillChange::REMOVE, AutofillKey(name, value))); | |
149 | |
150 // Post the notifications including the list of affected keys. | |
151 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
152 db_observer_list_, | |
153 AutofillEntriesChanged(changes)); | |
154 | |
155 return WebDatabase::COMMIT_NEEDED; | |
156 } | |
157 return WebDatabase::COMMIT_NOT_NEEDED; | |
158 } | |
159 | |
160 WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile( | |
161 const AutofillProfile& profile, WebDatabase* db) { | |
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
163 if (!AutofillTable::FromWebDatabase(db)->AddAutofillProfile(profile)) { | |
164 NOTREACHED(); | |
165 return WebDatabase::COMMIT_NOT_NEEDED; | |
166 } | |
167 | |
168 // Send GUID-based notification. | |
169 AutofillProfileChange change( | |
170 AutofillProfileChange::ADD, profile.guid(), &profile); | |
171 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
172 db_observer_list_, | |
173 AutofillProfileChanged(change)); | |
174 | |
175 return WebDatabase::COMMIT_NEEDED; | |
176 } | |
177 | |
178 WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile( | |
179 const AutofillProfile& profile, WebDatabase* db) { | |
180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
181 // Only perform the update if the profile exists. It is currently | |
182 // valid to try to update a missing profile. We simply drop the write and | |
183 // the caller will detect this on the next refresh. | |
184 AutofillProfile* original_profile = NULL; | |
185 if (!AutofillTable::FromWebDatabase(db)->GetAutofillProfile(profile.guid(), | |
186 &original_profile)) { | |
187 return WebDatabase::COMMIT_NOT_NEEDED; | |
188 } | |
189 scoped_ptr<AutofillProfile> scoped_profile(original_profile); | |
190 | |
191 if (!AutofillTable::FromWebDatabase(db)->UpdateAutofillProfile(profile)) { | |
192 NOTREACHED(); | |
193 return WebDatabase::COMMIT_NEEDED; | |
194 } | |
195 | |
196 // Send GUID-based notification. | |
197 AutofillProfileChange change( | |
198 AutofillProfileChange::UPDATE, profile.guid(), &profile); | |
199 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
200 db_observer_list_, | |
201 AutofillProfileChanged(change)); | |
202 | |
203 return WebDatabase::COMMIT_NEEDED; | |
204 } | |
205 | |
206 WebDatabase::State AutofillWebDataBackendImpl::RemoveAutofillProfile( | |
207 const std::string& guid, WebDatabase* db) { | |
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
209 AutofillProfile* profile = NULL; | |
210 if (!AutofillTable::FromWebDatabase(db)->GetAutofillProfile(guid, &profile)) { | |
211 NOTREACHED(); | |
212 return WebDatabase::COMMIT_NOT_NEEDED; | |
213 } | |
214 scoped_ptr<AutofillProfile> scoped_profile(profile); | |
215 | |
216 if (!AutofillTable::FromWebDatabase(db)->RemoveAutofillProfile(guid)) { | |
217 NOTREACHED(); | |
218 return WebDatabase::COMMIT_NOT_NEEDED; | |
219 } | |
220 | |
221 // Send GUID-based notification. | |
222 AutofillProfileChange change(AutofillProfileChange::REMOVE, guid, NULL); | |
223 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
224 db_observer_list_, | |
225 AutofillProfileChanged(change)); | |
226 | |
227 return WebDatabase::COMMIT_NEEDED; | |
228 } | |
229 | |
230 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetAutofillProfiles( | |
231 WebDatabase* db) { | |
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
233 std::vector<AutofillProfile*> profiles; | |
234 AutofillTable::FromWebDatabase(db)->GetAutofillProfiles(&profiles); | |
235 return scoped_ptr<WDTypedResult>( | |
236 new WDDestroyableResult<std::vector<AutofillProfile*> >( | |
237 AUTOFILL_PROFILES_RESULT, | |
238 profiles, | |
239 base::Bind(&AutofillWebDataBackendImpl::DestroyAutofillProfileResult, | |
240 base::Unretained(this)))); | |
241 } | |
242 | |
243 WebDatabase::State AutofillWebDataBackendImpl::AddCreditCard( | |
244 const CreditCard& credit_card, WebDatabase* db) { | |
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
246 if (!AutofillTable::FromWebDatabase(db)->AddCreditCard(credit_card)) { | |
247 NOTREACHED(); | |
248 return WebDatabase::COMMIT_NOT_NEEDED; | |
249 } | |
250 | |
251 return WebDatabase::COMMIT_NEEDED; | |
252 } | |
253 | |
254 WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard( | |
255 const CreditCard& credit_card, WebDatabase* db) { | |
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
257 // It is currently valid to try to update a missing profile. We simply drop | |
258 // the write and the caller will detect this on the next refresh. | |
259 CreditCard* original_credit_card = NULL; | |
260 if (!AutofillTable::FromWebDatabase(db)->GetCreditCard(credit_card.guid(), | |
261 &original_credit_card)) { | |
262 return WebDatabase::COMMIT_NOT_NEEDED; | |
263 } | |
264 scoped_ptr<CreditCard> scoped_credit_card(original_credit_card); | |
265 | |
266 if (!AutofillTable::FromWebDatabase(db)->UpdateCreditCard(credit_card)) { | |
267 NOTREACHED(); | |
268 return WebDatabase::COMMIT_NOT_NEEDED; | |
269 } | |
270 return WebDatabase::COMMIT_NEEDED; | |
271 } | |
272 | |
273 WebDatabase::State AutofillWebDataBackendImpl::RemoveCreditCard( | |
274 const std::string& guid, WebDatabase* db) { | |
275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
276 if (!AutofillTable::FromWebDatabase(db)->RemoveCreditCard(guid)) { | |
277 NOTREACHED(); | |
278 return WebDatabase::COMMIT_NOT_NEEDED; | |
279 } | |
280 return WebDatabase::COMMIT_NEEDED; | |
281 } | |
282 | |
283 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCards( | |
284 WebDatabase* db) { | |
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
286 std::vector<CreditCard*> credit_cards; | |
287 AutofillTable::FromWebDatabase(db)->GetCreditCards(&credit_cards); | |
288 return scoped_ptr<WDTypedResult>( | |
289 new WDDestroyableResult<std::vector<CreditCard*> >( | |
290 AUTOFILL_CREDITCARDS_RESULT, | |
291 credit_cards, | |
292 base::Bind(&AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult, | |
293 base::Unretained(this)))); | |
294 } | |
295 | |
296 WebDatabase::State | |
297 AutofillWebDataBackendImpl::RemoveAutofillDataModifiedBetween( | |
298 const base::Time& delete_begin, | |
299 const base::Time& delete_end, | |
300 WebDatabase* db) { | |
301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
302 std::vector<std::string> profile_guids; | |
303 std::vector<std::string> credit_card_guids; | |
304 if (AutofillTable::FromWebDatabase(db)->RemoveAutofillDataModifiedBetween( | |
305 delete_begin, | |
306 delete_end, | |
307 &profile_guids, | |
308 &credit_card_guids)) { | |
309 for (std::vector<std::string>::iterator iter = profile_guids.begin(); | |
310 iter != profile_guids.end(); ++iter) { | |
311 AutofillProfileChange change(AutofillProfileChange::REMOVE, *iter, NULL); | |
312 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
313 db_observer_list_, | |
314 AutofillProfileChanged(change)); | |
315 } | |
316 // Note: It is the caller's responsibility to post notifications for any | |
317 // changes, e.g. by calling the Refresh() method of PersonalDataManager. | |
318 return WebDatabase::COMMIT_NEEDED; | |
319 } | |
320 return WebDatabase::COMMIT_NOT_NEEDED; | |
321 } | |
322 | |
323 WebDatabase::State AutofillWebDataBackendImpl::RemoveOriginURLsModifiedBetween( | |
324 const base::Time& delete_begin, | |
325 const base::Time& delete_end, | |
326 WebDatabase* db) { | |
327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
328 ScopedVector<AutofillProfile> profiles; | |
329 if (AutofillTable::FromWebDatabase(db)->RemoveOriginURLsModifiedBetween( | |
330 delete_begin, delete_end, &profiles)) { | |
331 for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin(); | |
332 it != profiles.end(); ++it) { | |
333 AutofillProfileChange change(AutofillProfileChange::UPDATE, | |
334 (*it)->guid(), *it); | |
335 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
336 db_observer_list_, | |
337 AutofillProfileChanged(change)); | |
338 } | |
339 // Note: It is the caller's responsibility to post notifications for any | |
340 // changes, e.g. by calling the Refresh() method of PersonalDataManager. | |
341 return WebDatabase::COMMIT_NEEDED; | |
342 } | |
343 return WebDatabase::COMMIT_NOT_NEEDED; | |
344 } | |
345 | |
346 WebDatabase::State AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl( | |
347 WebDatabase* db) { | |
348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
349 AutofillChangeList changes; | |
350 | |
351 if (AutofillTable::FromWebDatabase(db)->RemoveExpiredFormElements(&changes)) { | |
352 if (!changes.empty()) { | |
353 // Post the notifications including the list of affected keys. | |
354 // This is sent here so that work resulting from this notification | |
355 // will be done on the DB thread, and not the UI thread. | |
356 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, | |
357 db_observer_list_, | |
358 AutofillEntriesChanged(changes)); | |
359 } | |
360 return WebDatabase::COMMIT_NEEDED; | |
361 } | |
362 return WebDatabase::COMMIT_NOT_NEEDED; | |
363 } | |
364 | |
365 void AutofillWebDataBackendImpl::DestroyAutofillProfileResult( | |
366 const WDTypedResult* result) { | |
367 DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT); | |
368 const WDResult<std::vector<AutofillProfile*> >* r = | |
369 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); | |
370 std::vector<AutofillProfile*> profiles = r->GetValue(); | |
371 STLDeleteElements(&profiles); | |
372 } | |
373 | |
374 void AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult( | |
375 const WDTypedResult* result) { | |
376 DCHECK(result->GetType() == AUTOFILL_CREDITCARDS_RESULT); | |
377 const WDResult<std::vector<CreditCard*> >* r = | |
378 static_cast<const WDResult<std::vector<CreditCard*> >*>(result); | |
379 | |
380 std::vector<CreditCard*> credit_cards = r->GetValue(); | |
381 STLDeleteElements(&credit_cards); | |
382 } | |
383 | |
384 } // namespace autofill | |
OLD | NEW |