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 287ce9484f4b200d272bfa591b9b67acf57ff668..91f0c8955c0363b4ae4209a5498c0ed2ec8448d1 100644 |
--- a/chrome/browser/autofill/personal_data_manager.cc |
+++ b/chrome/browser/autofill/personal_data_manager.cc |
@@ -11,12 +11,15 @@ |
#include "base/string_number_conversions.h" |
#include "base/utf_string_conversions.h" |
#include "chrome/browser/autofill/autofill-inl.h" |
+#include "chrome/browser/autofill/autofill_country.h" |
Ilya Sherman
2011/03/16 23:07:16
nit: No longer needed.
dhollowa
2011/03/17 00:02:42
Done.
|
#include "chrome/browser/autofill/autofill_field.h" |
#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 +85,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 |
@@ -166,6 +178,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. |
Ilya Sherman
2011/03/16 23:07:16
We already call into EmptyMigrationTrash() at vari
dhollowa
2011/03/17 00:02:42
It does the "empty" sooner in the cycle. I.e. as
|
+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) { |
@@ -253,12 +290,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; |
+ } |
} |
} |
} |
@@ -270,8 +310,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( |
@@ -629,6 +672,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); |
@@ -679,6 +804,7 @@ void PersonalDataManager::ReceiveLoadedProfiles(WebDataService::Handle h, |
} |
LogProfileCount(); |
+ EmptyMigrationTrash(); |
} |
void PersonalDataManager::ReceiveLoadedCreditCards( |
@@ -719,62 +845,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) { |
@@ -814,6 +884,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) { |