summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autofill
diff options
context:
space:
mode:
authordhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-11 19:26:05 +0000
committerdhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-11 19:26:05 +0000
commitd7da65dcddcfcf6c63cecdbedccdd6fd1cbf07d2 (patch)
treea60df142f8575775ea73bee896f6645363fd7472 /chrome/browser/autofill
parentf920f91f55cb5d549b5048716326ab21914bdff6 (diff)
downloadchromium_src-d7da65dcddcfcf6c63cecdbedccdd6fd1cbf07d2.zip
chromium_src-d7da65dcddcfcf6c63cecdbedccdd6fd1cbf07d2.tar.gz
chromium_src-d7da65dcddcfcf6c63cecdbedccdd6fd1cbf07d2.tar.bz2
Autofill form submission creates wrong credit cards.
Adds logic to filter out credit card submissions that are invalid, or to merge credit cards that match the card number. BUG=57975 TEST=PersonalDataManagerTest.Aggregate* Review URL: http://codereview.chromium.org/4734001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65830 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autofill')
-rw-r--r--chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm2
-rw-r--r--chrome/browser/autofill/autofill_ie_toolbar_import_win.cc9
-rw-r--r--chrome/browser/autofill/autofill_manager.cc2
-rw-r--r--chrome/browser/autofill/credit_card.cc25
-rw-r--r--chrome/browser/autofill/credit_card.h6
-rw-r--r--chrome/browser/autofill/form_group.cc10
-rw-r--r--chrome/browser/autofill/form_group.h3
-rw-r--r--chrome/browser/autofill/personal_data_manager.cc18
-rw-r--r--chrome/browser/autofill/personal_data_manager.h3
-rw-r--r--chrome/browser/autofill/personal_data_manager_unittest.cc443
10 files changed, 492 insertions, 29 deletions
diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm
index 13aeb4f..71c9ae8 100644
--- a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm
+++ b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm
@@ -271,7 +271,7 @@ TEST_F(AutoFillDialogControllerTest, CreditCardDataMutation) {
ASSERT_TRUE(sheet != nil);
AutoFillCreditCardModel* cm = [sheet creditCardModel];
EXPECT_TRUE([[cm nameOnCard] isEqualToString:@"DCH"]);
- EXPECT_TRUE([[cm creditCardNumber] isEqualToString:@"1234 5678 9101 1121"]);
+ EXPECT_TRUE([[cm creditCardNumber] isEqualToString:@"1234567891011121"]);
EXPECT_TRUE([[cm expirationMonth] isEqualToString:@"01"]);
EXPECT_TRUE([[cm expirationYear] isEqualToString:@"2012"]);
diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
index 0165f1c..2350607 100644
--- a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
+++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
@@ -133,6 +133,9 @@ bool ImportSingleProfile(FormGroup* profile,
string16 field_value = ReadAndDecryptValue(key, value_name.c_str());
if (!field_value.empty()) {
has_non_empty_fields = true;
+ if (it->second == CREDIT_CARD_NUMBER) {
+ field_value = DecryptCCNumber(field_value);
+ }
profile->SetInfo(AutoFillType(it->second), field_value);
}
}
@@ -237,12 +240,6 @@ bool ImportCurrentUserProfiles(std::vector<AutoFillProfile>* profiles,
if (ImportSingleProfile(&credit_card, &key, reg_to_field)) {
string16 cc_number = credit_card.GetFieldText(
AutoFillType(CREDIT_CARD_NUMBER));
-
- if (!cc_number.empty()) {
- // No additional password, and CC# is not empty, decrypt CC#.
- cc_number = DecryptCCNumber(cc_number);
- }
- credit_card.SetInfo(AutoFillType(CREDIT_CARD_NUMBER), cc_number);
if (!cc_number.empty())
credit_cards->push_back(credit_card);
}
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index e5056e2..6f89173 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -409,7 +409,7 @@ void AutoFillManager::HandleSubmit() {
// require querying the FormManager for updated field values.
std::vector<FormStructure*> import;
import.push_back(upload_form_structure_.get());
- if (!personal_data_->ImportFormData(import, this))
+ if (!personal_data_->ImportFormData(import))
return;
// Did we get credit card info?
diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc
index b4e92b8..b85e538 100644
--- a/chrome/browser/autofill/credit_card.cc
+++ b/chrome/browser/autofill/credit_card.cc
@@ -19,7 +19,6 @@
namespace {
-const string16::value_type kCreditCardSeparators[] = {' ','-',0};
const char* kCreditCardObfuscationString = "************";
const AutoFillFieldType kAutoFillCreditCardTypes[] = {
@@ -124,6 +123,16 @@ std::string GetCreditCardType(const string16& number) {
return kGenericCard;
}
+// Return a version of |number| that has had any non-digit values removed.
+const string16 RemoveNonAsciiDigits(const string16& number) {
+ string16 stripped;
+ for (size_t i = 0; i < number.size(); ++i) {
+ if (IsAsciiDigit(number[i]))
+ stripped.append(1, number[i]);
+ }
+ return stripped;
+}
+
} // namespace
CreditCard::CreditCard(const std::string& guid)
@@ -291,6 +300,10 @@ void CreditCard::SetInfo(const AutoFillType& type, const string16& value) {
SetExpirationMonthFromString(value);
break;
+ case CREDIT_CARD_EXP_2_DIGIT_YEAR:
+ // This is a read-only attribute.
+ break;
+
case CREDIT_CARD_EXP_4_DIGIT_YEAR:
SetExpirationYearFromString(value);
break;
@@ -404,8 +417,10 @@ bool CreditCard::operator!=(const CreditCard& credit_card) const {
// Use the Luhn formula to validate the number.
// static
bool CreditCard::IsCreditCardNumber(const string16& text) {
- string16 number;
- RemoveChars(text, kCreditCardSeparators, &number);
+ string16 number = RemoveNonAsciiDigits(text);
+
+ if (number.empty())
+ return false;
int sum = 0;
bool odd = false;
@@ -476,6 +491,10 @@ void CreditCard::SetExpirationYearFromString(const string16& text) {
set_expiration_year(year);
}
+void CreditCard::set_number(const string16& number) {
+ number_ = RemoveNonAsciiDigits(number);
+}
+
void CreditCard::set_expiration_month(int expiration_month) {
if (expiration_month < 0 || expiration_month > 12)
return;
diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h
index 91fc6ce..b6fdfde 100644
--- a/chrome/browser/autofill/credit_card.h
+++ b/chrome/browser/autofill/credit_card.h
@@ -70,6 +70,9 @@ class CreditCard : public FormGroup {
// Returns true if there are no values (field types) set.
bool IsEmpty() const;
+ // Returns the credit card number.
+ const string16& number() const { return number_; }
+
private:
// The month and year are zero if not present.
int Expiration4DigitYear() const { return expiration_year_; }
@@ -84,13 +87,12 @@ class CreditCard : public FormGroup {
// Sets |expiration_year_| to the integer conversion of |text|.
void SetExpirationYearFromString(const string16& text);
- const string16& number() const { return number_; }
const string16& name_on_card() const { return name_on_card_; }
const string16& last_four_digits() const { return last_four_digits_; }
int expiration_month() const { return expiration_month_; }
int expiration_year() const { return expiration_year_; }
- void set_number(const string16& number) { number_ = number; }
+ void set_number(const string16& number);
void set_name_on_card(const string16& name_on_card) {
name_on_card_ = name_on_card;
}
diff --git a/chrome/browser/autofill/form_group.cc b/chrome/browser/autofill/form_group.cc
index 7e91bc3..49beb16 100644
--- a/chrome/browser/autofill/form_group.cc
+++ b/chrome/browser/autofill/form_group.cc
@@ -76,3 +76,13 @@ void FormGroup::MergeWith(const FormGroup& form_group) {
SetInfo(type, form_group.GetFieldText(type));
}
}
+
+void FormGroup::OverwriteWith(const FormGroup& form_group) {
+ FieldTypeSet a;;
+ form_group.GetAvailableFieldTypes(&a);
+
+ for (FieldTypeSet::const_iterator iter = a.begin(); iter != a.end(); ++iter) {
+ AutoFillType type(*iter);
+ SetInfo(type, form_group.GetFieldText(type));
+ }
+}
diff --git a/chrome/browser/autofill/form_group.h b/chrome/browser/autofill/form_group.h
index 5f16276..b1b2243 100644
--- a/chrome/browser/autofill/form_group.h
+++ b/chrome/browser/autofill/form_group.h
@@ -69,6 +69,9 @@ class FormGroup {
// Merges the field data in |form_group| with this FormGroup.
void MergeWith(const FormGroup& form_group);
+
+ // Overwrites the field data in |form_group| with this FormGroup.
+ void OverwriteWith(const FormGroup& form_group);
};
#endif // CHROME_BROWSER_AUTOFILL_FORM_GROUP_H_
diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc
index 1fb398e..4264baf 100644
--- a/chrome/browser/autofill/personal_data_manager.cc
+++ b/chrome/browser/autofill/personal_data_manager.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/autofill/autofill_field.h"
#include "chrome/browser/autofill/form_structure.h"
#include "chrome/browser/autofill/phone_number.h"
@@ -169,8 +168,7 @@ void PersonalDataManager::RemoveObserver(
}
bool PersonalDataManager::ImportFormData(
- const std::vector<FormStructure*>& form_structures,
- AutoFillManager* autofill_manager) {
+ const std::vector<FormStructure*>& form_structures) {
// Parse the form and construct a profile based on the information that is
// possible to import.
int importable_fields = 0;
@@ -256,6 +254,13 @@ bool PersonalDataManager::ImportFormData(
if (importable_credit_card_fields == 0)
imported_credit_card_.reset();
+ if (imported_credit_card_.get()) {
+ if (!CreditCard::IsCreditCardNumber(imported_credit_card_->GetFieldText(
+ AutoFillType(CREDIT_CARD_NUMBER)))) {
+ imported_credit_card_.reset();
+ }
+ }
+
// We always save imported profiles.
SaveImportedProfile();
@@ -756,10 +761,13 @@ void PersonalDataManager::SaveImportedCreditCard() {
merged = true;
} else if ((*iter)->IntersectionOfTypesHasEqualValues(
*imported_credit_card_)) {
- // |imported_profile| contains all of the data in this profile, plus
- // more.
+ // |imported_profile| contains all of the data in this profile, plus more.
merged = true;
(*iter)->MergeWith(*imported_credit_card_);
+ } else if (!imported_credit_card_->number().empty() &&
+ (*iter)->number() == imported_credit_card_->number()) {
+ merged = true;
+ (*iter)->OverwriteWith(*imported_credit_card_);
}
creditcards.push_back(**iter);
diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h
index d73bc7c..2fd6d8a 100644
--- a/chrome/browser/autofill/personal_data_manager.h
+++ b/chrome/browser/autofill/personal_data_manager.h
@@ -67,8 +67,7 @@ class PersonalDataManager
// field types that contain information in the FormStructures a profile will
// be created with all of the information from recognized fields. Returns
// whether a profile was created.
- bool ImportFormData(const std::vector<FormStructure*>& form_structures,
- AutoFillManager* autofill_manager);
+ bool ImportFormData(const std::vector<FormStructure*>& form_structures);
// Gets |imported_profile_| and |imported_credit_card_| and returns their
// values in |profile| and |credit_card| parameters respectively. One or
diff --git a/chrome/browser/autofill/personal_data_manager_unittest.cc b/chrome/browser/autofill/personal_data_manager_unittest.cc
index 2947e08..cf83af9 100644
--- a/chrome/browser/autofill/personal_data_manager_unittest.cc
+++ b/chrome/browser/autofill/personal_data_manager_unittest.cc
@@ -500,7 +500,7 @@ TEST_F(PersonalDataManagerTest, Refresh) {
update.push_back(profile2);
personal_data_->SetProfiles(&update);
- // And wait for the refresh.
+ // Wait for the refresh.
EXPECT_CALL(personal_data_observer_,
OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
@@ -526,9 +526,9 @@ TEST_F(PersonalDataManagerTest, ImportFormData) {
FormStructure form_structure(form);
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
- personal_data_->ImportFormData(forms, NULL);
+ personal_data_->ImportFormData(forms);
- // And wait for the refresh.
+ // Wait for the refresh.
EXPECT_CALL(personal_data_observer_,
OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
@@ -622,9 +622,9 @@ TEST_F(PersonalDataManagerTest, AggregateProfileData) {
scoped_ptr<std::vector<FormStructure*> > forms(
new std::vector<FormStructure*>);
forms->push_back(form_structure.get());
- personal_data_->ImportFormData(*forms, NULL);
+ personal_data_->ImportFormData(*forms);
- // And wait for the refresh.
+ // Wait for the refresh.
EXPECT_CALL(personal_data_observer_,
OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
@@ -654,9 +654,9 @@ TEST_F(PersonalDataManagerTest, AggregateProfileData) {
form_structure.reset(new FormStructure(*form));
forms.reset(new std::vector<FormStructure*>);
forms->push_back(form_structure.get());
- personal_data_->ImportFormData(*forms, NULL);
+ personal_data_->ImportFormData(*forms);
- // And wait for the refresh.
+ // Wait for the refresh.
EXPECT_CALL(personal_data_observer_,
OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
@@ -701,9 +701,9 @@ TEST_F(PersonalDataManagerTest, AggregateProfileData) {
form_structure.reset(new FormStructure(*form));
forms.reset(new std::vector<FormStructure*>);
forms->push_back(form_structure.get());
- personal_data_->ImportFormData(*forms, NULL);
+ personal_data_->ImportFormData(*forms);
- // And wait for the refresh.
+ // Wait for the refresh.
EXPECT_CALL(personal_data_observer_,
OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
@@ -724,3 +724,428 @@ TEST_F(PersonalDataManagerTest, AggregateProfileData) {
NULL, NULL);
EXPECT_EQ(0, expected->Compare(*results3[1]));
}
+
+TEST_F(PersonalDataManagerTest, AggregateTwoDifferentCreditCards) {
+ FormData form1;
+
+ // Start with a single valid credit card form.
+ webkit_glue::FormField field;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form1.fields.push_back(field);
+
+ FormStructure form_structure1(form1);
+ std::vector<FormStructure*> forms;
+ forms.push_back(&form_structure1);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ CreditCard expected;
+ autofill_test::SetCreditCardInfo(&expected,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected.Compare(*results[0]));
+
+ // Add a second different valid credit card.
+ FormData form2;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Jim Johansen", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "5500 0000 0000 0004", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "02", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2012", "text", &field);
+ form2.fields.push_back(field);
+
+ FormStructure form_structure2(form2);
+ forms.clear();
+ forms.push_back(&form_structure2);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ CreditCard expected2;
+ autofill_test::SetCreditCardInfo(&expected2,
+ "L2", "Jim Johansen", "5500000000000004", "02", "2012");
+ const std::vector<CreditCard*>& results2 = personal_data_->credit_cards();
+ ASSERT_EQ(2U, results2.size());
+ EXPECT_EQ(0, expected.Compare(*results2[0]));
+ EXPECT_EQ(0, expected2.Compare(*results2[1]));
+}
+
+TEST_F(PersonalDataManagerTest, AggregateInvalidCreditCard) {
+ FormData form1;
+
+ // Start with a single valid credit card form.
+ webkit_glue::FormField field;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form1.fields.push_back(field);
+
+ FormStructure form_structure1(form1);
+ std::vector<FormStructure*> forms;
+ forms.push_back(&form_structure1);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ CreditCard expected;
+ autofill_test::SetCreditCardInfo(&expected,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected.Compare(*results[0]));
+
+ // Add a second different invalid credit card.
+ FormData form2;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Jim Johansen", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "1000000000000000", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "02", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2012", "text", &field);
+ form2.fields.push_back(field);
+
+ FormStructure form_structure2(form2);
+ forms.clear();
+ forms.push_back(&form_structure2);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Note: no refresh here.
+
+ const std::vector<CreditCard*>& results2 = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results2.size());
+ EXPECT_EQ(0, expected.Compare(*results2[0]));
+}
+
+TEST_F(PersonalDataManagerTest, AggregateSameCreditCardWithConflict) {
+ FormData form1;
+
+ // Start with a single valid credit card form.
+ webkit_glue::FormField field;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form1.fields.push_back(field);
+
+ FormStructure form_structure1(form1);
+ std::vector<FormStructure*> forms;
+ forms.push_back(&form_structure1);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ CreditCard expected;
+ autofill_test::SetCreditCardInfo(&expected,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected.Compare(*results[0]));
+
+ // Add a second different valid credit card where the year is different but
+ // the credit card number matches.
+ FormData form2;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111 1111 1111 1111", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2012", "text", &field);
+ form2.fields.push_back(field);
+
+ FormStructure form_structure2(form2);
+ forms.clear();
+ forms.push_back(&form_structure2);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ // Expect that the newer information is saved. In this case the year is
+ // updated to "2012".
+ CreditCard expected2;
+ autofill_test::SetCreditCardInfo(&expected2,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2012");
+ const std::vector<CreditCard*>& results2 = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results2.size());
+ EXPECT_EQ(0, expected2.Compare(*results2[0]));
+}
+
+TEST_F(PersonalDataManagerTest, AggregateEmptyCreditCardWithConflict) {
+ FormData form1;
+
+ // Start with a single valid credit card form.
+ webkit_glue::FormField field;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form1.fields.push_back(field);
+
+ FormStructure form_structure1(form1);
+ std::vector<FormStructure*> forms;
+ forms.push_back(&form_structure1);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ CreditCard expected;
+ autofill_test::SetCreditCardInfo(&expected,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected.Compare(*results[0]));
+
+ // Add a second credit card with no number.
+ FormData form2;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2012", "text", &field);
+ form2.fields.push_back(field);
+
+ FormStructure form_structure2(form2);
+ forms.clear();
+ forms.push_back(&form_structure2);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Note: no refresh here.
+
+ // No change is expected.
+ CreditCard expected2;
+ autofill_test::SetCreditCardInfo(&expected2,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results2 = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results2.size());
+ EXPECT_EQ(0, expected2.Compare(*results2[0]));
+}
+
+TEST_F(PersonalDataManagerTest, AggregateCreditCardWithMissingInfoInNew) {
+ FormData form1;
+
+ // Start with a single valid credit card form.
+ webkit_glue::FormField field;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form1.fields.push_back(field);
+
+ FormStructure form_structure1(form1);
+ std::vector<FormStructure*> forms;
+ forms.push_back(&form_structure1);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ CreditCard expected;
+ autofill_test::SetCreditCardInfo(&expected,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected.Compare(*results[0]));
+
+ // Add a second different valid credit card where the name is missing but
+ // the credit card number matches.
+ FormData form2;
+ // Note missing name.
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111111111111111", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form2.fields.push_back(field);
+
+ FormStructure form_structure2(form2);
+ forms.clear();
+ forms.push_back(&form_structure2);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ // No change is expected.
+ CreditCard expected2;
+ autofill_test::SetCreditCardInfo(&expected2,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results2 = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results2.size());
+ EXPECT_EQ(0, expected2.Compare(*results2[0]));
+}
+
+TEST_F(PersonalDataManagerTest, AggregateCreditCardWithMissingInfoInOld) {
+ FormData form1;
+
+ // Start with a single valid credit card form.
+ webkit_glue::FormField field;
+ // Note missing name.
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form1.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form1.fields.push_back(field);
+
+ FormStructure form_structure1(form1);
+ std::vector<FormStructure*> forms;
+ forms.push_back(&form_structure1);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ CreditCard expected;
+ autofill_test::SetCreditCardInfo(&expected,
+ "L1", NULL, "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected.Compare(*results[0]));
+
+ // Add a second different valid credit card where the year is different but
+ // the credit card number matches.
+ FormData form2;
+ autofill_test::CreateTestFormField(
+ "Name on card:", "name_on_card", "Biggie Smalls", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Card Number:", "card_number", "4111-1111-1111-1111", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Month:", "exp_month", "01", "text", &field);
+ form2.fields.push_back(field);
+ autofill_test::CreateTestFormField(
+ "Exp Year:", "exp_year", "2011", "text", &field);
+ form2.fields.push_back(field);
+
+ FormStructure form_structure2(form2);
+ forms.clear();
+ forms.push_back(&form_structure2);
+ personal_data_->ImportFormData(forms);
+ personal_data_->SaveImportedCreditCard();
+
+ // Wait for the refresh.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ MessageLoop::current()->Run();
+
+ // Expect that the newer information is saved. In this case the year is
+ // added to the existing credit card.
+ CreditCard expected2;
+ autofill_test::SetCreditCardInfo(&expected2,
+ "L1", "Biggie Smalls", "4111111111111111", "01", "2011");
+ const std::vector<CreditCard*>& results2 = personal_data_->credit_cards();
+ ASSERT_EQ(1U, results2.size());
+ EXPECT_EQ(0, expected2.Compare(*results2[0]));
+}
+