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