diff options
author | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-31 17:43:01 +0000 |
---|---|---|
committer | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-31 17:43:01 +0000 |
commit | 224d21b895ef373bdaaf12960004e2b5d4e2b1b5 (patch) | |
tree | edae7ffc526abdde069994accdfdb99278545f63 | |
parent | 1252b9a069a1f79116252d6bbc47fbac92e0f732 (diff) | |
download | chromium_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.cc | 91 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card_field.cc | 39 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card_field.h | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card_field_unittest.cc | 257 | ||||
-rw-r--r-- | chrome/browser/autofill/form_structure_unittest.cc | 70 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
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', |