| Index: chrome/browser/autofill/personal_data_manager.cc
|
| diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc
|
| index c21d31db98b08cf18c6fb76a775cbed0dda0426b..f41c37b3851c74d32a4c5c6dbcf51824f75b2435 100644
|
| --- a/chrome/browser/autofill/personal_data_manager.cc
|
| +++ b/chrome/browser/autofill/personal_data_manager.cc
|
| @@ -15,8 +15,10 @@
|
| #include "chrome/browser/autofill/autofill_metrics.h"
|
| #include "chrome/browser/autofill/form_structure.h"
|
| #include "chrome/browser/autofill/phone_number.h"
|
| +#include "chrome/browser/autofill/select_control_handler.h"
|
| #include "chrome/browser/prefs/pref_service.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/sync/profile_sync_service.h"
|
| #include "chrome/browser/webdata/web_data_service.h"
|
| #include "chrome/common/pref_names.h"
|
| #include "content/browser/browser_thread.h"
|
| @@ -82,6 +84,15 @@ bool IsValidEmail(const string16& value) {
|
| return re.match(WebKit::WebString(StringToLowerASCII(value))) != -1;
|
| }
|
|
|
| +// Valid for US zip codes only.
|
| +bool IsValidZip(const string16& value) {
|
| + // Basic US zip code matching.
|
| + const string16 kZipPattern = ASCIIToUTF16("^\\d{5}(-\\d{4})?$");
|
| + WebKit::WebRegularExpression re(WebKit::WebString(kZipPattern),
|
| + WebKit::WebTextCaseInsensitive);
|
| + return re.match(WebKit::WebString(StringToLowerASCII(value))) != -1;
|
| +}
|
| +
|
| // Returns true if minimum requirements for import of a given |profile| have
|
| // been met. An address submitted via a form must have at least these fields
|
| // filled. No verification of validity of the contents is preformed. This is
|
| @@ -151,6 +162,31 @@ void PersonalDataManager::RemoveObserver(
|
| observers_.RemoveObserver(observer);
|
| }
|
|
|
| +// The |PersonalDataManager| is set up as a listener of the sync service in
|
| +// |EmptyMigrationTrash| in the case where sync is not yet ready to receive
|
| +// changes. This method, |OnStateChange| acts as a deferred call to
|
| +// |EmptyMigrationTrash| once the sync service becomes available.
|
| +void PersonalDataManager::OnStateChanged() {
|
| + if (!profile_ || profile_->IsOffTheRecord())
|
| + return;
|
| +
|
| + WebDataService* web_data_service =
|
| + profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
|
| + if (!web_data_service) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + ProfileSyncService* sync_service = profile_->GetProfileSyncService();
|
| + if (!sync_service)
|
| + return;
|
| +
|
| + if (sync_service->ShouldPushChanges()) {
|
| + web_data_service->EmptyMigrationTrash(true);
|
| + sync_service->RemoveObserver(this);
|
| + }
|
| +}
|
| +
|
| bool PersonalDataManager::ImportFormData(
|
| const std::vector<const FormStructure*>& form_structures,
|
| const CreditCard** imported_credit_card) {
|
| @@ -238,12 +274,15 @@ bool PersonalDataManager::ImportFormData(
|
| }
|
| }
|
|
|
| - if (field_type.field_type() == EMAIL_ADDRESS && !IsValidEmail(value))
|
| - continue;
|
| -
|
| - imported_profile->SetInfo(AutofillType(field_type.field_type()),
|
| - value);
|
| + imported_profile->SetInfo(AutofillType(field_type.field_type()), value);
|
| ++importable_fields;
|
| +
|
| + // Reject profiles with invalid country information.
|
| + if (field_type.field_type() == ADDRESS_HOME_COUNTRY &&
|
| + !value.empty() && imported_profile->CountryCode().empty()) {
|
| + imported_profile.reset();
|
| + break;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -255,8 +294,11 @@ bool PersonalDataManager::ImportFormData(
|
| if (importable_credit_card_fields < kMinCreditCardImportSize)
|
| local_imported_credit_card.reset();
|
|
|
| - if (imported_profile.get() && !IsMinimumAddress(*imported_profile.get()))
|
| + // Reject if minimum address and validation requirements are not met.
|
| + if (imported_profile.get() &&
|
| + !IsValidLearnableProfile(*imported_profile.get())) {
|
| imported_profile.reset();
|
| + }
|
|
|
| if (local_imported_credit_card.get() &&
|
| !CreditCard::IsCreditCardNumber(local_imported_credit_card->GetFieldText(
|
| @@ -614,6 +656,88 @@ void PersonalDataManager::Init(Profile* profile) {
|
| LoadCreditCards();
|
| }
|
|
|
| +// static
|
| +bool PersonalDataManager::IsValidLearnableProfile(
|
| + const AutofillProfile& profile) {
|
| + if (!IsMinimumAddress(profile))
|
| + return false;
|
| +
|
| + string16 email = profile.GetFieldText(AutofillType(EMAIL_ADDRESS));
|
| + if (!email.empty() && !IsValidEmail(email))
|
| + return false;
|
| +
|
| + // Reject profiles with invalid US state information.
|
| + string16 state = profile.GetFieldText(AutofillType(ADDRESS_HOME_STATE));
|
| + if (profile.CountryCode() == "US" &&
|
| + !state.empty() && !autofill::IsValidState(state)) {
|
| + return false;
|
| + }
|
| +
|
| + // Reject profiles with invalid US zip information.
|
| + string16 zip = profile.GetFieldText(AutofillType(ADDRESS_HOME_ZIP));
|
| + if (profile.CountryCode() == "US" && !zip.empty() && !IsValidZip(zip))
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// static
|
| +bool PersonalDataManager::MergeProfile(
|
| + const AutofillProfile& profile,
|
| + const std::vector<AutofillProfile*>& existing_profiles,
|
| + std::vector<AutofillProfile>* merged_profiles) {
|
| + DCHECK(merged_profiles);
|
| + merged_profiles->clear();
|
| +
|
| + // Set to true if |profile| is merged into |existing_profiles|.
|
| + bool merged = false;
|
| +
|
| + // First preference is to add missing values to an existing profile.
|
| + // Only merge with the first match.
|
| + for (std::vector<AutofillProfile*>::const_iterator iter =
|
| + existing_profiles.begin();
|
| + iter != existing_profiles.end(); ++iter) {
|
| + if (!merged) {
|
| + if (profile.IsSubsetOf(**iter)) {
|
| + // In this case, the existing profile already contains all of the data
|
| + // in |profile|, so consider the profiles already merged.
|
| + merged = true;
|
| + } else if ((*iter)->IntersectionOfTypesHasEqualValues(profile)) {
|
| + // |profile| contains all of the data in this profile, plus more.
|
| + merged = true;
|
| + (*iter)->MergeWith(profile);
|
| + }
|
| + }
|
| + merged_profiles->push_back(**iter);
|
| + }
|
| +
|
| + // The second preference, if not merged above, is to alter non-primary values
|
| + // where the primary values match.
|
| + // Again, only merge with the first match.
|
| + if (!merged) {
|
| + merged_profiles->clear();
|
| + for (std::vector<AutofillProfile*>::const_iterator iter =
|
| + existing_profiles.begin();
|
| + iter != existing_profiles.end(); ++iter) {
|
| + if (!merged) {
|
| + if (!profile.PrimaryValue().empty() &&
|
| + (*iter)->PrimaryValue() == profile.PrimaryValue()) {
|
| + merged = true;
|
| + (*iter)->OverwriteWith(profile);
|
| + }
|
| + }
|
| + merged_profiles->push_back(**iter);
|
| + }
|
| + }
|
| +
|
| + // Finally, if the new profile was not merged with an existing profile then
|
| + // add the new profile to the list.
|
| + if (!merged)
|
| + merged_profiles->push_back(profile);
|
| +
|
| + return merged;
|
| +}
|
| +
|
| void PersonalDataManager::LoadProfiles() {
|
| WebDataService* web_data_service =
|
| profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
|
| @@ -664,6 +788,7 @@ void PersonalDataManager::ReceiveLoadedProfiles(WebDataService::Handle h,
|
| }
|
|
|
| LogProfileCount();
|
| + EmptyMigrationTrash();
|
| }
|
|
|
| void PersonalDataManager::ReceiveLoadedCreditCards(
|
| @@ -704,62 +829,6 @@ void PersonalDataManager::SaveImportedProfile(
|
| AddProfile(imported_profile);
|
| }
|
|
|
| -bool PersonalDataManager::MergeProfile(
|
| - const AutofillProfile& profile,
|
| - const std::vector<AutofillProfile*>& existing_profiles,
|
| - std::vector<AutofillProfile>* merged_profiles) {
|
| - DCHECK(merged_profiles);
|
| - merged_profiles->clear();
|
| -
|
| - // Set to true if |profile| is merged into |existing_profiles|.
|
| - bool merged = false;
|
| -
|
| - // First preference is to add missing values to an existing profile.
|
| - // Only merge with the first match.
|
| - for (std::vector<AutofillProfile*>::const_iterator iter =
|
| - existing_profiles.begin();
|
| - iter != existing_profiles.end(); ++iter) {
|
| - if (!merged) {
|
| - if (profile.IsSubsetOf(**iter)) {
|
| - // In this case, the existing profile already contains all of the data
|
| - // in |profile|, so consider the profiles already merged.
|
| - merged = true;
|
| - } else if ((*iter)->IntersectionOfTypesHasEqualValues(profile)) {
|
| - // |profile| contains all of the data in this profile, plus more.
|
| - merged = true;
|
| - (*iter)->MergeWith(profile);
|
| - }
|
| - }
|
| - merged_profiles->push_back(**iter);
|
| - }
|
| -
|
| - // The second preference, if not merged above, is to alter non-primary values
|
| - // where the primary values match.
|
| - // Again, only merge with the first match.
|
| - if (!merged) {
|
| - merged_profiles->clear();
|
| - for (std::vector<AutofillProfile*>::const_iterator iter =
|
| - existing_profiles.begin();
|
| - iter != existing_profiles.end(); ++iter) {
|
| - if (!merged) {
|
| - if (!profile.PrimaryValue().empty() &&
|
| - (*iter)->PrimaryValue() == profile.PrimaryValue()) {
|
| - merged = true;
|
| - (*iter)->OverwriteWith(profile);
|
| - }
|
| - }
|
| - merged_profiles->push_back(**iter);
|
| - }
|
| - }
|
| -
|
| - // Finally, if the new profile was not merged with an existing profile then
|
| - // add the new profile to the list.
|
| - if (!merged)
|
| - merged_profiles->push_back(profile);
|
| -
|
| - return merged;
|
| -}
|
| -
|
|
|
| void PersonalDataManager::SaveImportedCreditCard(
|
| const CreditCard& imported_credit_card) {
|
| @@ -799,6 +868,32 @@ void PersonalDataManager::SaveImportedCreditCard(
|
| SetCreditCards(&creditcards);
|
| }
|
|
|
| +void PersonalDataManager::EmptyMigrationTrash() {
|
| + if (!profile_ || profile_->IsOffTheRecord())
|
| + return;
|
| +
|
| + WebDataService* web_data_service =
|
| + profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
|
| + if (!web_data_service) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + ProfileSyncService* sync_service = profile_->GetProfileSyncService();
|
| + if (!sync_service)
|
| + return;
|
| +
|
| + if (!sync_service->HasSyncSetupCompleted()) {
|
| + web_data_service->EmptyMigrationTrash(false);
|
| + } else if (sync_service->ShouldPushChanges()) {
|
| + web_data_service->EmptyMigrationTrash(true);
|
| + } else {
|
| + // Install ourself as a listener so we can empty the trash once the
|
| + // sync service becomes available.
|
| + if (!sync_service->HasObserver(this))
|
| + sync_service->AddObserver(this);
|
| + }
|
| +}
|
|
|
| void PersonalDataManager::LogProfileCount() const {
|
| if (!g_has_logged_profile_count) {
|
|
|