• Home
  • 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 
AddCreditCard(const CreditCard & credit_card,WebDatabase * db)248 WebDatabase::State AutofillWebDataBackendImpl::AddCreditCard(
249     const CreditCard& credit_card, WebDatabase* db) {
250   DCHECK(db_thread_->BelongsToCurrentThread());
251   if (!AutofillTable::FromWebDatabase(db)->AddCreditCard(credit_card)) {
252     NOTREACHED();
253     return WebDatabase::COMMIT_NOT_NEEDED;
254   }
255 
256   return WebDatabase::COMMIT_NEEDED;
257 }
258 
UpdateCreditCard(const CreditCard & credit_card,WebDatabase * db)259 WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard(
260     const CreditCard& credit_card, WebDatabase* db) {
261   DCHECK(db_thread_->BelongsToCurrentThread());
262   // It is currently valid to try to update a missing profile.  We simply drop
263   // the write and the caller will detect this on the next refresh.
264   CreditCard* original_credit_card = NULL;
265   if (!AutofillTable::FromWebDatabase(db)->GetCreditCard(credit_card.guid(),
266       &original_credit_card)) {
267     return WebDatabase::COMMIT_NOT_NEEDED;
268   }
269   scoped_ptr<CreditCard> scoped_credit_card(original_credit_card);
270 
271   if (!AutofillTable::FromWebDatabase(db)->UpdateCreditCard(credit_card)) {
272     NOTREACHED();
273     return WebDatabase::COMMIT_NOT_NEEDED;
274   }
275   return WebDatabase::COMMIT_NEEDED;
276 }
277 
RemoveCreditCard(const std::string & guid,WebDatabase * db)278 WebDatabase::State AutofillWebDataBackendImpl::RemoveCreditCard(
279     const std::string& guid, WebDatabase* db) {
280   DCHECK(db_thread_->BelongsToCurrentThread());
281   if (!AutofillTable::FromWebDatabase(db)->RemoveCreditCard(guid)) {
282     NOTREACHED();
283     return WebDatabase::COMMIT_NOT_NEEDED;
284   }
285   return WebDatabase::COMMIT_NEEDED;
286 }
287 
GetCreditCards(WebDatabase * db)288 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCards(
289     WebDatabase* db) {
290   DCHECK(db_thread_->BelongsToCurrentThread());
291   std::vector<CreditCard*> credit_cards;
292   AutofillTable::FromWebDatabase(db)->GetCreditCards(&credit_cards);
293   return scoped_ptr<WDTypedResult>(
294       new WDDestroyableResult<std::vector<CreditCard*> >(
295           AUTOFILL_CREDITCARDS_RESULT,
296           credit_cards,
297         base::Bind(&AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult,
298               base::Unretained(this))));
299 }
300 
301 WebDatabase::State
RemoveAutofillDataModifiedBetween(const base::Time & delete_begin,const base::Time & delete_end,WebDatabase * db)302     AutofillWebDataBackendImpl::RemoveAutofillDataModifiedBetween(
303         const base::Time& delete_begin,
304         const base::Time& delete_end,
305         WebDatabase* db) {
306   DCHECK(db_thread_->BelongsToCurrentThread());
307   std::vector<std::string> profile_guids;
308   std::vector<std::string> credit_card_guids;
309   if (AutofillTable::FromWebDatabase(db)->RemoveAutofillDataModifiedBetween(
310           delete_begin,
311           delete_end,
312           &profile_guids,
313           &credit_card_guids)) {
314     for (std::vector<std::string>::iterator iter = profile_guids.begin();
315          iter != profile_guids.end(); ++iter) {
316       AutofillProfileChange change(AutofillProfileChange::REMOVE, *iter, NULL);
317       FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
318                         db_observer_list_,
319                         AutofillProfileChanged(change));
320     }
321     // Note: It is the caller's responsibility to post notifications for any
322     // changes, e.g. by calling the Refresh() method of PersonalDataManager.
323     return WebDatabase::COMMIT_NEEDED;
324   }
325   return WebDatabase::COMMIT_NOT_NEEDED;
326 }
327 
RemoveOriginURLsModifiedBetween(const base::Time & delete_begin,const base::Time & delete_end,WebDatabase * db)328 WebDatabase::State AutofillWebDataBackendImpl::RemoveOriginURLsModifiedBetween(
329     const base::Time& delete_begin,
330     const base::Time& delete_end,
331     WebDatabase* db) {
332   DCHECK(db_thread_->BelongsToCurrentThread());
333   ScopedVector<AutofillProfile> profiles;
334   if (AutofillTable::FromWebDatabase(db)->RemoveOriginURLsModifiedBetween(
335           delete_begin, delete_end, &profiles)) {
336     for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin();
337          it != profiles.end(); ++it) {
338       AutofillProfileChange change(AutofillProfileChange::UPDATE,
339                                    (*it)->guid(), *it);
340       FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
341                         db_observer_list_,
342                         AutofillProfileChanged(change));
343     }
344     // Note: It is the caller's responsibility to post notifications for any
345     // changes, e.g. by calling the Refresh() method of PersonalDataManager.
346     return WebDatabase::COMMIT_NEEDED;
347   }
348   return WebDatabase::COMMIT_NOT_NEEDED;
349 }
350 
RemoveExpiredFormElementsImpl(WebDatabase * db)351 WebDatabase::State AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl(
352     WebDatabase* db) {
353   DCHECK(db_thread_->BelongsToCurrentThread());
354   AutofillChangeList changes;
355 
356   if (AutofillTable::FromWebDatabase(db)->RemoveExpiredFormElements(&changes)) {
357     if (!changes.empty()) {
358       // Post the notifications including the list of affected keys.
359       // This is sent here so that work resulting from this notification
360       // will be done on the DB thread, and not the UI thread.
361       FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
362                         db_observer_list_,
363                         AutofillEntriesChanged(changes));
364     }
365     return WebDatabase::COMMIT_NEEDED;
366   }
367   return WebDatabase::COMMIT_NOT_NEEDED;
368 }
369 
DestroyAutofillProfileResult(const WDTypedResult * result)370 void AutofillWebDataBackendImpl::DestroyAutofillProfileResult(
371     const WDTypedResult* result) {
372   DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT);
373   const WDResult<std::vector<AutofillProfile*> >* r =
374       static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result);
375   std::vector<AutofillProfile*> profiles = r->GetValue();
376   STLDeleteElements(&profiles);
377 }
378 
DestroyAutofillCreditCardResult(const WDTypedResult * result)379 void AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult(
380       const WDTypedResult* result) {
381   DCHECK(result->GetType() == AUTOFILL_CREDITCARDS_RESULT);
382   const WDResult<std::vector<CreditCard*> >* r =
383       static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
384 
385   std::vector<CreditCard*> credit_cards = r->GetValue();
386   STLDeleteElements(&credit_cards);
387 }
388 
389 }  // namespace autofill
390