Home | History | Annotate | Download | only in webdata
      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 
     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 
     40 void AutofillWebDataBackendImpl::AddObserver(
     41     AutofillWebDataServiceObserverOnDBThread* observer) {
     42   DCHECK(db_thread_->BelongsToCurrentThread());
     43   db_observer_list_.AddObserver(observer);
     44 }
     45 
     46 void AutofillWebDataBackendImpl::RemoveObserver(
     47     AutofillWebDataServiceObserverOnDBThread* observer) {
     48   DCHECK(db_thread_->BelongsToCurrentThread());
     49   db_observer_list_.RemoveObserver(observer);
     50 }
     51 
     52 AutofillWebDataBackendImpl::~AutofillWebDataBackendImpl() {
     53   DCHECK(!user_data_.get()); // Forgot to call ResetUserData?
     54 }
     55 
     56 WebDatabase* AutofillWebDataBackendImpl::GetDatabase() {
     57   DCHECK(db_thread_->BelongsToCurrentThread());
     58   return web_database_backend_->database();
     59 }
     60 
     61 void AutofillWebDataBackendImpl::RemoveExpiredFormElements() {
     62   web_database_backend_->ExecuteWriteTask(
     63       Bind(&AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl,
     64            this));
     65 }
     66 
     67 void AutofillWebDataBackendImpl::NotifyOfMultipleAutofillChanges() {
     68   DCHECK(db_thread_->BelongsToCurrentThread());
     69   ui_thread_->PostTask(FROM_HERE, on_changed_callback_);
     70 }
     71 
     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 
     79 void AutofillWebDataBackendImpl::ResetUserData() {
     80   user_data_.reset();
     81 }
     82 
     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>
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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