summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-31 17:43:01 +0000
committerdhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-31 17:43:01 +0000
commit224d21b895ef373bdaaf12960004e2b5d4e2b1b5 (patch)
treeedae7ffc526abdde069994accdfdb99278545f63
parent1252b9a069a1f79116252d6bbc47fbac92e0f732 (diff)
downloadchromium_src-224d21b895ef373bdaaf12960004e2b5d4e2b1b5.zip
chromium_src-224d21b895ef373bdaaf12960004e2b5d4e2b1b5.tar.gz
chromium_src-224d21b895ef373bdaaf12960004e2b5d4e2b1b5.tar.bz2
AutoFill credit card field filling.
Adds logic to heuristically determine when credit card fields are present in a form and fills in user-provided credit card data into form fields when appropriate. BUG=38320 TEST=CreditCardFieldTest, FormStructureTest, manual testing with cc.html (attached). Review URL: http://codereview.chromium.org/1534005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43233 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autofill/autofill_manager.cc91
-rw-r--r--chrome/browser/autofill/credit_card_field.cc39
-rw-r--r--chrome/browser/autofill/credit_card_field.h4
-rw-r--r--chrome/browser/autofill/credit_card_field_unittest.cc257
-rw-r--r--chrome/browser/autofill/form_structure_unittest.cc70
-rw-r--r--chrome/chrome_tests.gypi1
6 files changed, 441 insertions, 21 deletions
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index 54dbe9b..5734291 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -106,7 +106,8 @@ bool AutoFillManager::GetAutoFillSuggestions(
return false;
const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles();
- if (profiles.empty())
+ const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
+ if (profiles.empty() && credit_cards.empty())
return false;
AutoFillFieldType type = UNKNOWN_TYPE;
@@ -123,6 +124,20 @@ bool AutoFillManager::GetAutoFillSuggestions(
if (*form_field != field)
continue;
+ if (form_field->possible_types().find(CREDIT_CARD_NAME) !=
+ form_field->possible_types().end() ||
+ form_field->heuristic_type() == CREDIT_CARD_NAME) {
+ type = CREDIT_CARD_NAME;
+ break;
+ }
+
+ if (form_field->possible_types().find(CREDIT_CARD_NUMBER) !=
+ form_field->possible_types().end() ||
+ form_field->heuristic_type() == CREDIT_CARD_NUMBER) {
+ type = CREDIT_CARD_NUMBER;
+ break;
+ }
+
if (form_field->possible_types().find(NAME_FIRST) !=
form_field->possible_types().end() ||
form_field->heuristic_type() == NAME_FIRST) {
@@ -144,15 +159,38 @@ bool AutoFillManager::GetAutoFillSuggestions(
std::vector<string16> names;
std::vector<string16> labels;
- for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin();
- iter != profiles.end(); ++iter) {
- string16 name = (*iter)->GetFieldText(AutoFillType(type));
- string16 label = (*iter)->Label();
- // TODO(jhawkins): What if name.length() == 0?
- if (StartsWith(name, field.value(), false)) {
- names.push_back(name);
- labels.push_back(label);
+ // Check for credit card suggestions.
+ if (type == CREDIT_CARD_NAME || type == CREDIT_CARD_NUMBER) {
+ for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
+ iter != credit_cards.end(); ++iter) {
+ // TODO(jhawkins): What if GetFieldText(...).length() == 0?
+ if (StartsWith((*iter)->GetFieldText(AutoFillType(type)),
+ field.value(), false)) {
+ string16 name;
+ if (type == CREDIT_CARD_NUMBER) {
+ name = (*iter)->ObfuscatedNumber();
+ } else {
+ name = (*iter)->GetFieldText(AutoFillType(type));
+ }
+ string16 label = (*iter)->Label();
+
+ names.push_back(name);
+ labels.push_back(label);
+ }
+ }
+ } else if (type == NAME_FIRST || type == NAME_FULL) {
+ for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin();
+ iter != profiles.end(); ++iter) {
+ // TODO(jhawkins): What if GetFieldText(...).length() == 0?
+ if (StartsWith((*iter)->GetFieldText(AutoFillType(type)),
+ field.value(), false)) {
+ string16 name = (*iter)->GetFieldText(AutoFillType(type));
+ string16 label = (*iter)->Label();
+
+ names.push_back(name);
+ labels.push_back(label);
+ }
}
}
@@ -178,9 +216,11 @@ bool AutoFillManager::FillAutoFillFormData(int query_id,
return false;
const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles();
- if (profiles.empty())
+ const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
+ if (profiles.empty() && credit_cards.empty())
return false;
+ // Find profile that matches |name| and |label| in question.
const AutoFillProfile* profile = NULL;
for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin();
iter != profiles.end(); ++iter) {
@@ -195,7 +235,24 @@ bool AutoFillManager::FillAutoFillFormData(int query_id,
break;
}
- if (!profile)
+ // Only look for credit card info if we're not filling profile.
+ const CreditCard* credit_card = NULL;
+ if (!profile) {
+ for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
+ iter != credit_cards.end(); ++iter) {
+ if ((*iter)->Label() != label)
+ continue;
+
+ if ((*iter)->GetFieldText(AutoFillType(CREDIT_CARD_NAME)) != name &&
+ (*iter)->ObfuscatedNumber() != name)
+ continue;
+
+ credit_card = *iter;
+ break;
+ }
+ }
+
+ if (!profile && !credit_card)
return false;
webkit_glue::FormData result = form;
@@ -211,8 +268,16 @@ bool AutoFillManager::FillAutoFillFormData(int query_id,
for (size_t j = 0; j < result.fields.size(); ++j) {
if (field->name() == result.fields[j].name()) {
- result.fields[j].set_value(
- profile->GetFieldText(AutoFillType(field->heuristic_type())));
+ AutoFillType autofill_type(field->heuristic_type());
+ if (credit_card) {
+ result.fields[j].set_value(
+ credit_card->GetFieldText(autofill_type));
+ } else if (profile) {
+ result.fields[j].set_value(
+ profile->GetFieldText(autofill_type));
+ } else {
+ NOTREACHED();
+ }
break;
}
}
diff --git a/chrome/browser/autofill/credit_card_field.cc b/chrome/browser/autofill/credit_card_field.cc
index 3a2bebc..b79467d 100644
--- a/chrome/browser/autofill/credit_card_field.cc
+++ b/chrome/browser/autofill/credit_card_field.cc
@@ -8,7 +8,31 @@
#include "chrome/browser/autofill/autofill_field.h"
bool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const {
- return false;
+ bool ok = Add(field_type_map, number_, AutoFillType(CREDIT_CARD_NUMBER));
+ DCHECK(ok);
+
+ // If the heuristics detected first and last name in separate fields,
+ // then ignore both fields. Putting them into separate fields is probably
+ // wrong, because the credit card can also contain a middle name or middle
+ // initial.
+ if (cardholder_last_ == NULL) {
+ // Add() will check if cardholder_ is != NULL.
+ Add(field_type_map, cardholder_, AutoFillType(CREDIT_CARD_NAME));
+ }
+
+ Add(field_type_map, type_, AutoFillType(CREDIT_CARD_TYPE));
+
+ ok = ok && Add(field_type_map, expiration_month_,
+ AutoFillType(CREDIT_CARD_EXP_MONTH));
+ DCHECK(ok);
+ ok = ok && Add(field_type_map, expiration_year_,
+ AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+ DCHECK(ok);
+
+ Add(field_type_map, verification_,
+ AutoFillType(CREDIT_CARD_VERIFICATION_CODE));
+
+ return ok;
}
// static
@@ -20,7 +44,9 @@ CreditCardField* CreditCardField::Parse(
string16 pattern;
// Credit card fields can appear in many different orders.
- for (int fields = 0; q != *iter; ++fields) {
+ // We loop until no more credit card related fields are found, see |break| at
+ // bottom of the loop.
+ for (int fields = 0; true; ++fields) {
// Sometimes the cardholder field is just labeled "name" (e.g. on test page
// Starbucks - Credit card.html). Unfortunately this is a dangerously
// generic word to search for, since it will often match a name (not
@@ -126,15 +152,18 @@ CreditCardField* CreditCardField::Parse(
// Some pages (e.g. ExpediaBilling.html) have a "card description"
// field; we parse this field but ignore it.
- ParseText(&q, ASCIIToUTF16("card description"));
+ if (ParseText(&q, ASCIIToUTF16("card description")))
+ continue;
+
+ break;
}
// On some pages, the user selects a card type using radio buttons
// (e.g. test page Apple Store Billing.html). We can't handle that yet,
// so we treat the card type as optional for now.
- if (credit_card_field.number_ != NULL &&
+ if (credit_card_field.number_ &&
credit_card_field.expiration_month_ &&
- !credit_card_field.expiration_month_->IsEmpty()) {
+ credit_card_field.expiration_year_) {
*iter = q;
return new CreditCardField(credit_card_field);
}
diff --git a/chrome/browser/autofill/credit_card_field.h b/chrome/browser/autofill/credit_card_field.h
index bad1eb9..cf3545e 100644
--- a/chrome/browser/autofill/credit_card_field.h
+++ b/chrome/browser/autofill/credit_card_field.h
@@ -38,12 +38,12 @@ class CreditCardField : public FormField {
AutoFillField* cardholder_last_;
AutoFillField* type_; // Optional. TODO(jhawkins): Parse the select control.
- AutoFillField* number_;
+ AutoFillField* number_; // Required.
// The 3-digit card verification number; we don't currently fill this.
AutoFillField* verification_;
- // Both optional. TODO(jhawkins): Parse the select control.
+ // Both required. TODO(jhawkins): Parse the select control.
AutoFillField* expiration_month_;
AutoFillField* expiration_year_;
};
diff --git a/chrome/browser/autofill/credit_card_field_unittest.cc b/chrome/browser/autofill/credit_card_field_unittest.cc
new file mode 100644
index 0000000..efadf7a
--- /dev/null
+++ b/chrome/browser/autofill/credit_card_field_unittest.cc
@@ -0,0 +1,257 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_ptr.h"
+#include "base/scoped_vector.h"
+#include "chrome/browser/autofill/credit_card_field.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/form_field_values.h"
+
+namespace {
+
+class CreditCardFieldTest : public testing::Test {
+ public:
+ CreditCardFieldTest() {}
+
+ protected:
+ ScopedVector<AutoFillField> list_;
+ scoped_ptr<CreditCardField> field_;
+ FieldTypeMap field_type_map_;
+ std::vector<AutoFillField*>::const_iterator iter_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CreditCardFieldTest);
+};
+
+TEST_F(CreditCardFieldTest, Empty) {
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_EQ(static_cast<CreditCardField*>(NULL), field_.get());
+}
+
+TEST_F(CreditCardFieldTest, NonParse) {
+ list_.push_back(new AutoFillField);
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_EQ(static_cast<CreditCardField*>(NULL), field_.get());
+}
+
+TEST_F(CreditCardFieldTest, ParseCreditCardNoNumber) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Month"),
+ ASCIIToUTF16("ccmonth"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("month1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"),
+ ASCIIToUTF16("ccyear"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("year1")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_EQ(static_cast<CreditCardField*>(NULL), field_.get());
+}
+
+TEST_F(CreditCardFieldTest, ParseCreditCardNoDate) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"),
+ ASCIIToUTF16("card_number"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("number1")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_EQ(static_cast<CreditCardField*>(NULL), field_.get());
+}
+
+TEST_F(CreditCardFieldTest, ParseMiniumCreditCard) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"),
+ ASCIIToUTF16("card_number"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("number1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Month"),
+ ASCIIToUTF16("ccmonth"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("month1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"),
+ ASCIIToUTF16("ccyear"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("year1")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_NE(static_cast<CreditCardField*>(NULL), field_.get());
+ ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("number1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, field_type_map_[ASCIIToUTF16("number1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("month1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, field_type_map_[ASCIIToUTF16("month1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("year1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ field_type_map_[ASCIIToUTF16("year1")]);
+}
+
+TEST_F(CreditCardFieldTest, ParseMiniumCreditCardEcml) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"),
+ kEcmlCardNumber,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("number1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Month"),
+ kEcmlCardExpireMonth,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("month1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"),
+ kEcmlCardExpireYear,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("year1")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_NE(static_cast<CreditCardField*>(NULL), field_.get());
+ ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("number1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, field_type_map_[ASCIIToUTF16("number1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("month1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, field_type_map_[ASCIIToUTF16("month1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("year1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ field_type_map_[ASCIIToUTF16("year1")]);
+}
+
+TEST_F(CreditCardFieldTest, ParseFullCreditCard) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Name on Card"),
+ ASCIIToUTF16("name on card"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("name1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"),
+ ASCIIToUTF16("card_number"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("number1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Month"),
+ ASCIIToUTF16("ccmonth"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("month1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"),
+ ASCIIToUTF16("ccyear"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("year1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Verification"),
+ ASCIIToUTF16("verification"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("cvc1")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_NE(static_cast<CreditCardField*>(NULL), field_.get());
+ ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("name1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_NAME, field_type_map_[ASCIIToUTF16("name1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("number1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, field_type_map_[ASCIIToUTF16("number1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("month1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, field_type_map_[ASCIIToUTF16("month1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("year1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ field_type_map_[ASCIIToUTF16("year1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("cvc1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_VERIFICATION_CODE,
+ field_type_map_[ASCIIToUTF16("cvc1")]);
+}
+
+TEST_F(CreditCardFieldTest, ParseFullCreditCardEcml) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Name on Card"),
+ kEcmlCardHolder,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("name1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"),
+ kEcmlCardNumber,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("number1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Month"),
+ kEcmlCardExpireMonth,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("month1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"),
+ kEcmlCardExpireYear,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("year1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Verification"),
+ kEcmlCardVerification,
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("cvc1")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(CreditCardField::Parse(&iter_, false));
+ ASSERT_NE(static_cast<CreditCardField*>(NULL), field_.get());
+ ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("name1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_NAME, field_type_map_[ASCIIToUTF16("name1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("number1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, field_type_map_[ASCIIToUTF16("number1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("month1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, field_type_map_[ASCIIToUTF16("month1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("year1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ field_type_map_[ASCIIToUTF16("year1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("cvc1")) != field_type_map_.end());
+ EXPECT_EQ(CREDIT_CARD_VERIFICATION_CODE,
+ field_type_map_[ASCIIToUTF16("cvc1")]);
+}
+
+} // namespace
+
diff --git a/chrome/browser/autofill/form_structure_unittest.cc b/chrome/browser/autofill/form_structure_unittest.cc
index 5b310b4..f528d24 100644
--- a/chrome/browser/autofill/form_structure_unittest.cc
+++ b/chrome/browser/autofill/form_structure_unittest.cc
@@ -85,7 +85,7 @@ TEST(FormStructureTest, IsAutoFillable) {
EXPECT_TRUE(form_structure->IsAutoFillable());
}
-TEST(FormStructureTest, Heuristics) {
+TEST(FormStructureTest, HeuristicsContactInfo) {
scoped_ptr<FormStructure> form_structure;
webkit_glue::FormFieldValues values;
@@ -438,4 +438,72 @@ TEST(FormStructureTest, HeuristicsLabelsOnly) {
EXPECT_EQ(ADDRESS_HOME_ZIP, form_structure->field(7)->heuristic_type());
}
+TEST(FormStructureTest, HeuristicsCreditCardInfo) {
+ scoped_ptr<FormStructure> form_structure;
+ webkit_glue::FormFieldValues values;
+
+ values.method = ASCIIToUTF16("post");
+ values.elements.push_back(webkit_glue::FormField(ASCIIToUTF16("Name on Card"),
+ ASCIIToUTF16("name on card"),
+ string16(),
+ ASCIIToUTF16("text")));
+ values.elements.push_back(webkit_glue::FormField(ASCIIToUTF16("Card Number"),
+ ASCIIToUTF16("card_number"),
+ string16(),
+ ASCIIToUTF16("text")));
+ values.elements.push_back(webkit_glue::FormField(ASCIIToUTF16("Exp Month"),
+ ASCIIToUTF16("ccmonth"),
+ string16(),
+ ASCIIToUTF16("text")));
+ values.elements.push_back(webkit_glue::FormField(ASCIIToUTF16("Exp Year"),
+ ASCIIToUTF16("ccyear"),
+ string16(),
+ ASCIIToUTF16("text")));
+ values.elements.push_back(webkit_glue::FormField(ASCIIToUTF16("Verification"),
+ ASCIIToUTF16("verification"),
+ string16(),
+ ASCIIToUTF16("text")));
+ values.elements.push_back(webkit_glue::FormField(string16(),
+ ASCIIToUTF16("Submit"),
+ string16(),
+ ASCIIToUTF16("submit")));
+ form_structure.reset(new FormStructure(values));
+ EXPECT_TRUE(form_structure->IsAutoFillable());
+
+ // Expect the correct number of fields.
+ ASSERT_EQ(5UL, form_structure->field_count());
+
+ // Check that heuristics are initialized as UNKNOWN_TYPE.
+ std::vector<AutoFillField*>::const_iterator iter;
+ size_t i;
+ for (iter = form_structure->begin(), i = 0;
+ iter != form_structure->end();
+ ++iter, ++i) {
+ // Expect last element to be NULL.
+ if (i == form_structure->field_count()) {
+ ASSERT_EQ(static_cast<AutoFillField*>(NULL), *iter);
+ } else {
+ ASSERT_NE(static_cast<AutoFillField*>(NULL), *iter);
+ EXPECT_EQ(UNKNOWN_TYPE, (*iter)->heuristic_type());
+ }
+ }
+
+ // Compute heuristic types.
+ form_structure->GetHeuristicAutoFillTypes();
+ ASSERT_EQ(5U, form_structure->field_count());
+
+ // Credit card name.
+ EXPECT_EQ(CREDIT_CARD_NAME, form_structure->field(0)->heuristic_type());
+ // Credit card number.
+ EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(1)->heuristic_type());
+ // Credit card expiration month.
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, form_structure->field(2)->heuristic_type());
+ // Credit card expiration year.
+ EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ form_structure->field(3)->heuristic_type());
+ // Credit card cvc.
+ EXPECT_EQ(CREDIT_CARD_VERIFICATION_CODE,
+ form_structure->field(4)->heuristic_type());
+}
+
} // namespace
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 53ca3d5..26fa29d 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -552,6 +552,7 @@
'browser/autofill/autofill_profile_unittest.cc',
'browser/autofill/autofill_xml_parser_unittest.cc',
'browser/autofill/billing_address_unittest.cc',
+ 'browser/autofill/credit_card_field_unittest.cc',
'browser/autofill/credit_card_unittest.cc',
'browser/autofill/form_structure_unittest.cc',
'browser/autofill/personal_data_manager_unittest.cc',