Index: chrome/browser/webdata/autofill_web_data_service_impl.cc |
diff --git a/chrome/browser/webdata/autofill_web_data_service_impl.cc b/chrome/browser/webdata/autofill_web_data_service_impl.cc |
index 07804ab2bada810da69e639e867bffc5ace64959..76dd5833620a0b5011644920a9fda50d2984930d 100644 |
--- a/chrome/browser/webdata/autofill_web_data_service_impl.cc |
+++ b/chrome/browser/webdata/autofill_web_data_service_impl.cc |
@@ -5,95 +5,419 @@ |
#include "chrome/browser/webdata/autofill_web_data_service_impl.h" |
#include "base/logging.h" |
-#include "chrome/browser/webdata/web_data_service.h" |
+#include "base/stl_util.h" |
+#include "chrome/browser/webdata/autofill_change.h" |
+#include "chrome/browser/webdata/autofill_entry.h" |
+#include "chrome/browser/webdata/autofill_table.h" |
+#include "chrome/browser/webdata/web_database_service.h" |
+#include "chrome/common/chrome_notification_types.h" |
+#include "components/autofill/browser/autofill_country.h" |
+#include "components/autofill/browser/autofill_profile.h" |
+#include "components/autofill/browser/credit_card.h" |
+#include "components/autofill/common/form_field_data.h" |
+#include "content/public/browser/notification_details.h" |
+#include "content/public/browser/notification_service.h" |
+#include "content/public/browser/notification_source.h" |
+ |
+using base::Bind; |
+using base::Time; |
+using content::BrowserThread; |
+ |
+namespace { |
+ |
+// A task used by AutofillWebDataService (for Sync mainly) to inform the |
+// PersonalDataManager living on the UI thread that it needs to refresh. |
+void NotifyOfMultipleAutofillChangesTask( |
+ const scoped_refptr<AutofillWebDataService>& web_data_service) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_MULTIPLE_CHANGED, |
+ content::Source<AutofillWebDataService>(web_data_service.get()), |
+ content::NotificationService::NoDetails()); |
+} |
+} |
+ |
+// static |
+void AutofillWebDataService::NotifyOfMultipleAutofillChanges( |
+ AutofillWebDataService* web_data_service) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ |
+ if (!web_data_service) |
+ return; |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ Bind(&NotifyOfMultipleAutofillChangesTask, |
+ make_scoped_refptr(web_data_service))); |
+} |
+ |
+AutofillWebDataService::AutofillWebDataService( |
+ scoped_refptr<WebDatabaseService> wdbs, |
+ const ProfileErrorCallback& callback) |
+ : WebDataServiceBase(wdbs, callback) { |
+} |
AutofillWebDataService::AutofillWebDataService() |
- : WebDataServiceBase(WebDataServiceBase::ProfileErrorCallback()) { |
+ : WebDataServiceBase(NULL, |
+ WebDataServiceBase::ProfileErrorCallback()) { |
} |
AutofillWebDataServiceImpl::AutofillWebDataServiceImpl( |
- scoped_refptr<WebDataService> service) |
- : service_(service) { |
- DCHECK(service.get()); |
+ scoped_refptr<WebDatabaseService> wdbs, |
+ const ProfileErrorCallback& callback) |
+ : AutofillWebDataService(wdbs, callback) { |
} |
-AutofillWebDataServiceImpl::~AutofillWebDataServiceImpl() { |
+content::NotificationSource |
+AutofillWebDataServiceImpl::GetNotificationSource() { |
+ return content::Source<AutofillWebDataService>(this); |
} |
void AutofillWebDataServiceImpl::AddFormFields( |
const std::vector<FormFieldData>& fields) { |
- service_->AddFormFields(fields); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::AddFormElementsImpl, this, fields)); |
} |
WebDataServiceBase::Handle |
AutofillWebDataServiceImpl::GetFormValuesForElementName( |
- const string16& name, |
- const string16& prefix, |
- int limit, |
+ const string16& name, const string16& prefix, int limit, |
WebDataServiceConsumer* consumer) { |
- return service_->GetFormValuesForElementName(name, prefix, limit, consumer); |
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::GetFormValuesForElementNameImpl, |
+ this, name, prefix, limit), consumer); |
} |
void AutofillWebDataServiceImpl::RemoveExpiredFormElements() { |
- service_->RemoveExpiredFormElements(); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::RemoveExpiredFormElementsImpl, this)); |
} |
void AutofillWebDataServiceImpl::RemoveFormValueForElementName( |
const string16& name, const string16& value) { |
- service_->RemoveFormValueForElementName(name, value); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::RemoveFormValueForElementNameImpl, |
+ this, name, value)); |
} |
void AutofillWebDataServiceImpl::AddAutofillProfile( |
const AutofillProfile& profile) { |
- service_->AddAutofillProfile(profile); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::AddAutofillProfileImpl, this, profile)); |
} |
void AutofillWebDataServiceImpl::UpdateAutofillProfile( |
const AutofillProfile& profile) { |
- service_->UpdateAutofillProfile(profile); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::UpdateAutofillProfileImpl, |
+ this, profile)); |
} |
void AutofillWebDataServiceImpl::RemoveAutofillProfile( |
const std::string& guid) { |
- service_->RemoveAutofillProfile(guid); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::RemoveAutofillProfileImpl, this, guid)); |
} |
WebDataServiceBase::Handle AutofillWebDataServiceImpl::GetAutofillProfiles( |
WebDataServiceConsumer* consumer) { |
- return service_->GetAutofillProfiles(consumer); |
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::GetAutofillProfilesImpl, this), |
+ consumer); |
} |
void AutofillWebDataServiceImpl::AddCreditCard(const CreditCard& credit_card) { |
- service_->AddCreditCard(credit_card); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::AddCreditCardImpl, this, credit_card)); |
} |
void AutofillWebDataServiceImpl::UpdateCreditCard( |
const CreditCard& credit_card) { |
- service_->UpdateCreditCard(credit_card); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::UpdateCreditCardImpl, this, |
+ credit_card)); |
} |
void AutofillWebDataServiceImpl::RemoveCreditCard(const std::string& guid) { |
- service_->RemoveCreditCard(guid); |
+ wdbs_->ScheduleDBTask(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::RemoveCreditCardImpl, this, guid)); |
} |
-WebDataServiceBase::Handle |
-AutofillWebDataServiceImpl::GetCreditCards(WebDataServiceConsumer* consumer) { |
- return service_->GetCreditCards(consumer); |
+AutofillWebDataServiceImpl::Handle AutofillWebDataServiceImpl::GetCreditCards( |
+ WebDataServiceConsumer* consumer) { |
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE, |
+ Bind(&AutofillWebDataServiceImpl::GetCreditCardsImpl, this), consumer); |
} |
-void AutofillWebDataServiceImpl::CancelRequest(Handle h) { |
- service_->CancelRequest(h); |
+AutofillWebDataServiceImpl::~AutofillWebDataServiceImpl() { |
} |
-content::NotificationSource |
-AutofillWebDataServiceImpl::GetNotificationSource() { |
- return service_->GetNotificationSource(); |
+//////////////////////////////////////////////////////////////////////////////// |
+// |
+// Autofill implementation. |
+// |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
+WebDatabase::State AutofillWebDataServiceImpl::AddFormElementsImpl( |
+ const std::vector<FormFieldData>& fields, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ AutofillChangeList changes; |
+ if (!AutofillTable::FromWebDatabase(db)->AddFormFieldValues( |
+ fields, &changes)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ |
+ // Post the notifications including the list of affected keys. |
+ // This is sent here so that work resulting from this notification will be |
+ // done on the DB thread, and not the UI thread. |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, |
+ content::Source<AutofillWebDataService>(this), |
+ content::Details<AutofillChangeList>(&changes)); |
+ |
+ return WebDatabase::COMMIT_NEEDED; |
+} |
+ |
+scoped_ptr<WDTypedResult> |
+AutofillWebDataServiceImpl::GetFormValuesForElementNameImpl( |
+ const string16& name, const string16& prefix, int limit, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ std::vector<string16> values; |
+ AutofillTable::FromWebDatabase(db)->GetFormValuesForElementName( |
+ name, prefix, &values, limit); |
+ return scoped_ptr<WDTypedResult>( |
+ new WDResult<std::vector<string16> >(AUTOFILL_VALUE_RESULT, values)); |
+} |
+ |
+WebDatabase::State |
+AutofillWebDataServiceImpl::RemoveFormElementsAddedBetweenImpl( |
+ const base::Time& delete_begin, const base::Time& delete_end, |
+ WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ AutofillChangeList changes; |
+ |
+ if (AutofillTable::FromWebDatabase(db)->RemoveFormElementsAddedBetween( |
+ delete_begin, delete_end, &changes)) { |
+ if (!changes.empty()) { |
+ // Post the notifications including the list of affected keys. |
+ // This is sent here so that work resulting from this notification |
+ // will be done on the DB thread, and not the UI thread. |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, |
+ content::Source<AutofillWebDataService>(this), |
+ content::Details<AutofillChangeList>(&changes)); |
+ } |
+ return WebDatabase::COMMIT_NEEDED; |
+ } |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
} |
-bool AutofillWebDataServiceImpl::IsDatabaseLoaded() { |
- return service_->IsDatabaseLoaded(); |
+WebDatabase::State |
+AutofillWebDataServiceImpl::RemoveExpiredFormElementsImpl( |
+ WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ AutofillChangeList changes; |
+ |
+ if (AutofillTable::FromWebDatabase(db)->RemoveExpiredFormElements(&changes)) { |
+ if (!changes.empty()) { |
+ // Post the notifications including the list of affected keys. |
+ // This is sent here so that work resulting from this notification |
+ // will be done on the DB thread, and not the UI thread. |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, |
+ content::Source<AutofillWebDataService>(this), |
+ content::Details<AutofillChangeList>(&changes)); |
+ } |
+ return WebDatabase::COMMIT_NEEDED; |
+ } |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
} |
-WebDatabase* AutofillWebDataServiceImpl::GetDatabase() { |
- return service_->GetDatabase(); |
+WebDatabase::State |
+AutofillWebDataServiceImpl::RemoveFormValueForElementNameImpl( |
+ const string16& name, const string16& value, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ |
+ if (AutofillTable::FromWebDatabase(db)->RemoveFormElement(name, value)) { |
+ AutofillChangeList changes; |
+ changes.push_back(AutofillChange(AutofillChange::REMOVE, |
+ AutofillKey(name, value))); |
+ |
+ // Post the notifications including the list of affected keys. |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, |
+ content::Source<AutofillWebDataService>(this), |
+ content::Details<AutofillChangeList>(&changes)); |
+ |
+ return WebDatabase::COMMIT_NEEDED; |
+ } |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+} |
+ |
+WebDatabase::State |
+AutofillWebDataServiceImpl::AddAutofillProfileImpl( |
+ const AutofillProfile& profile, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ if (!AutofillTable::FromWebDatabase(db)->AddAutofillProfile(profile)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ |
+ // Send GUID-based notification. |
+ AutofillProfileChange change(AutofillProfileChange::ADD, |
+ profile.guid(), &profile); |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED, |
+ content::Source<AutofillWebDataService>(this), |
+ content::Details<AutofillProfileChange>(&change)); |
+ |
+ return WebDatabase::COMMIT_NEEDED; |
+} |
+ |
+WebDatabase::State |
+AutofillWebDataServiceImpl::UpdateAutofillProfileImpl( |
+ const AutofillProfile& profile, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ // Only perform the update if the profile exists. It is currently |
+ // valid to try to update a missing profile. We simply drop the write and |
+ // the caller will detect this on the next refresh. |
+ AutofillProfile* original_profile = NULL; |
+ if (!AutofillTable::FromWebDatabase(db)->GetAutofillProfile(profile.guid(), |
+ &original_profile)) { |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ scoped_ptr<AutofillProfile> scoped_profile(original_profile); |
+ |
+ if (!AutofillTable::FromWebDatabase(db)->UpdateAutofillProfileMulti( |
+ profile)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NEEDED; |
+ } |
+ |
+ // Send GUID-based notification. |
+ AutofillProfileChange change(AutofillProfileChange::UPDATE, |
+ profile.guid(), &profile); |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED, |
+ content::Source<AutofillWebDataService>(this), |
+ content::Details<AutofillProfileChange>(&change)); |
+ |
+ return WebDatabase::COMMIT_NEEDED; |
+} |
+ |
+WebDatabase::State |
+AutofillWebDataServiceImpl::RemoveAutofillProfileImpl( |
+ const std::string& guid, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ AutofillProfile* profile = NULL; |
+ if (!AutofillTable::FromWebDatabase(db)->GetAutofillProfile(guid, &profile)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ scoped_ptr<AutofillProfile> scoped_profile(profile); |
+ |
+ if (!AutofillTable::FromWebDatabase(db)->RemoveAutofillProfile(guid)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ |
+ // Send GUID-based notification. |
+ AutofillProfileChange change(AutofillProfileChange::REMOVE, guid, NULL); |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED, |
+ content::Source<AutofillWebDataService>(this), |
+ content::Details<AutofillProfileChange>(&change)); |
+ |
+ return WebDatabase::COMMIT_NEEDED; |
+} |
+ |
+scoped_ptr<WDTypedResult> |
+AutofillWebDataServiceImpl::GetAutofillProfilesImpl( |
+ WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ std::vector<AutofillProfile*> profiles; |
+ AutofillTable::FromWebDatabase(db)->GetAutofillProfiles(&profiles); |
+ return scoped_ptr<WDTypedResult>( |
+ new WDDestroyableResult<std::vector<AutofillProfile*> >( |
+ AUTOFILL_PROFILES_RESULT, |
+ profiles, |
+ base::Bind(&AutofillWebDataServiceImpl::DestroyAutofillProfileResult, |
+ base::Unretained(this)))); |
+} |
+ |
+WebDatabase::State |
+AutofillWebDataServiceImpl::AddCreditCardImpl( |
+ const CreditCard& credit_card, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ if (!AutofillTable::FromWebDatabase(db)->AddCreditCard(credit_card)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ |
+ return WebDatabase::COMMIT_NEEDED; |
+} |
+ |
+WebDatabase::State |
+AutofillWebDataServiceImpl::UpdateCreditCardImpl( |
+ const CreditCard& credit_card, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ // It is currently valid to try to update a missing profile. We simply drop |
+ // the write and the caller will detect this on the next refresh. |
+ CreditCard* original_credit_card = NULL; |
+ if (!AutofillTable::FromWebDatabase(db)->GetCreditCard(credit_card.guid(), |
+ &original_credit_card)) { |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ scoped_ptr<CreditCard> scoped_credit_card(original_credit_card); |
+ |
+ if (!AutofillTable::FromWebDatabase(db)->UpdateCreditCard(credit_card)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ return WebDatabase::COMMIT_NEEDED; |
+} |
+ |
+WebDatabase::State |
+AutofillWebDataServiceImpl::RemoveCreditCardImpl( |
+ const std::string& guid, WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ if (!AutofillTable::FromWebDatabase(db)->RemoveCreditCard(guid)) { |
+ NOTREACHED(); |
+ return WebDatabase::COMMIT_NOT_NEEDED; |
+ } |
+ return WebDatabase::COMMIT_NEEDED; |
+} |
+ |
+scoped_ptr<WDTypedResult> |
+AutofillWebDataServiceImpl::GetCreditCardsImpl(WebDatabase* db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ std::vector<CreditCard*> credit_cards; |
+ AutofillTable::FromWebDatabase(db)->GetCreditCards(&credit_cards); |
+ return scoped_ptr<WDTypedResult>( |
+ new WDDestroyableResult<std::vector<CreditCard*> >( |
+ AUTOFILL_CREDITCARDS_RESULT, |
+ credit_cards, |
+ base::Bind(&AutofillWebDataServiceImpl::DestroyAutofillCreditCardResult, |
+ base::Unretained(this)))); |
+} |
+ |
+void AutofillWebDataServiceImpl::DestroyAutofillProfileResult( |
+ const WDTypedResult* result) { |
+ DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT); |
+ const WDResult<std::vector<AutofillProfile*> >* r = |
+ static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); |
+ std::vector<AutofillProfile*> profiles = r->GetValue(); |
+ STLDeleteElements(&profiles); |
+} |
+ |
+void AutofillWebDataServiceImpl::DestroyAutofillCreditCardResult( |
+ const WDTypedResult* result) { |
+ DCHECK(result->GetType() == AUTOFILL_CREDITCARDS_RESULT); |
+ const WDResult<std::vector<CreditCard*> >* r = |
+ static_cast<const WDResult<std::vector<CreditCard*> >*>(result); |
+ |
+ std::vector<CreditCard*> credit_cards = r->GetValue(); |
+ STLDeleteElements(&credit_cards); |
} |