diff options
author | Ben Murdoch <benm@google.com> | 2011-01-07 14:18:56 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-01-11 10:23:13 +0000 |
commit | 201ade2fbba22bfb27ae029f4d23fca6ded109a0 (patch) | |
tree | b793f4ed916f73cf18357ea467ff3deb5ffb5b52 /chrome/browser/autofill | |
parent | d8c4c37a7d0961944bfdfaa117d5c68c8e129c97 (diff) | |
download | external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.zip external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.tar.gz external_chromium-201ade2fbba22bfb27ae029f4d23fca6ded109a0.tar.bz2 |
Merge chromium at 9.0.597.55: Initial merge by git.
Change-Id: Id686a88437441ec7e17abb3328a404c7b6c3c6ad
Diffstat (limited to 'chrome/browser/autofill')
25 files changed, 2132 insertions, 1252 deletions
diff --git a/chrome/browser/autofill/address_field_unittest.cc b/chrome/browser/autofill/address_field_unittest.cc index 51509f7..d6a42db 100644 --- a/chrome/browser/autofill/address_field_unittest.cc +++ b/chrome/browser/autofill/address_field_unittest.cc @@ -46,7 +46,8 @@ TEST_F(AddressFieldTest, ParseOneLineAddress) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -66,7 +67,8 @@ TEST_F(AddressFieldTest, ParseOneLineAddressBilling) { ASCIIToUTF16("billingAddress"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -86,7 +88,8 @@ TEST_F(AddressFieldTest, ParseOneLineAddressShipping) { ASCIIToUTF16("shippingAddress"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -107,7 +110,8 @@ TEST_F(AddressFieldTest, ParseOneLineAddressEcml) { ASCIIToUTF16(kEcmlShipToAddress1), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -127,14 +131,16 @@ TEST_F(AddressFieldTest, ParseTwoLineAddress) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), string16(), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -157,21 +163,24 @@ TEST_F(AddressFieldTest, ParseThreeLineAddress) { ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Address Line2"), ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr2"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Address Line3"), ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr3"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -197,7 +206,8 @@ TEST_F(AddressFieldTest, ParseTwoLineAddressEcml) { ASCIIToUTF16(kEcmlShipToAddress1), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back( new AutoFillField( @@ -205,7 +215,8 @@ TEST_F(AddressFieldTest, ParseTwoLineAddressEcml) { ASCIIToUTF16(kEcmlShipToAddress2), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -228,7 +239,8 @@ TEST_F(AddressFieldTest, ParseCity) { ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("city1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -248,7 +260,8 @@ TEST_F(AddressFieldTest, ParseCityEcml) { ASCIIToUTF16(kEcmlShipToCity), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("city1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -268,7 +281,8 @@ TEST_F(AddressFieldTest, ParseState) { ASCIIToUTF16("state"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("state1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -289,7 +303,8 @@ TEST_F(AddressFieldTest, ParseStateEcml) { ASCIIToUTF16(kEcmlShipToStateProv), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("state1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -309,7 +324,8 @@ TEST_F(AddressFieldTest, ParseZip) { ASCIIToUTF16("zip"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("zip1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -330,7 +346,8 @@ TEST_F(AddressFieldTest, ParseZipEcml) { ASCIIToUTF16(kEcmlShipToPostalCode), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("zip1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -352,7 +369,8 @@ TEST_F(AddressFieldTest, ParseStateAndZipOneLabel) { ASCIIToUTF16("state"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("state"))); list_.push_back( new AutoFillField( @@ -361,7 +379,8 @@ TEST_F(AddressFieldTest, ParseStateAndZipOneLabel) { ASCIIToUTF16("zip"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("zip"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -384,7 +403,8 @@ TEST_F(AddressFieldTest, ParseCountry) { ASCIIToUTF16("country"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("country1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -404,7 +424,8 @@ TEST_F(AddressFieldTest, ParseCountryEcml) { ASCIIToUTF16(kEcmlShipToCountry), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("country1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -424,14 +445,16 @@ TEST_F(AddressFieldTest, ParseTwoLineAddressMissingLabel) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("bogus"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("addr2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -454,7 +477,8 @@ TEST_F(AddressFieldTest, ParseCompany) { ASCIIToUTF16("company"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("company1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -475,7 +499,8 @@ TEST_F(AddressFieldTest, ParseCompanyEcml) { ASCIIToUTF16(kEcmlShipToCompanyName), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("company1"))); list_.push_back(NULL); iter_ = list_.begin(); diff --git a/chrome/browser/autofill/autofill_common_test.cc b/chrome/browser/autofill/autofill_common_test.cc index c4c8482..32041cc 100644 --- a/chrome/browser/autofill/autofill_common_test.cc +++ b/chrome/browser/autofill/autofill_common_test.cc @@ -21,7 +21,8 @@ void CreateTestFormField(const char* label, const char* type, webkit_glue::FormField* field) { *field = webkit_glue::FormField(ASCIIToUTF16(label), ASCIIToUTF16(name), - ASCIIToUTF16(value), ASCIIToUTF16(type), 0); + ASCIIToUTF16(value), ASCIIToUTF16(type), 0, + false); } inline void check_and_set( diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.mm b/chrome/browser/autofill/autofill_dialog_controller_mac.mm index c1f193c..d2df304 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac.mm +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.mm @@ -13,12 +13,12 @@ #import "chrome/browser/autofill/autofill_credit_card_model_mac.h" #import "chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h" #import "chrome/browser/autofill/personal_data_manager.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #import "chrome/browser/cocoa/window_size_autosaver.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "chrome/common/notification_details.h" #include "chrome/common/notification_observer.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/autofill/autofill_download.cc b/chrome/browser/autofill/autofill_download.cc index a75cef6..1354a96 100644 --- a/chrome/browser/autofill/autofill_download.cc +++ b/chrome/browser/autofill/autofill_download.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/rand_util.h" #include "base/stl_util-inl.h" +#include "chrome/browser/autofill/autofill_metrics.h" #include "chrome/browser/autofill/autofill_xml_parser.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" @@ -78,6 +79,7 @@ bool AutoFillDownloadManager::StartQueryRequest( return false; request_data.request_type = AutoFillDownloadManager::REQUEST_QUERY; + autofill_metrics::LogServerQueryMetric(autofill_metrics::QUERY_SENT); return StartRequest(form_xml, request_data); } diff --git a/chrome/browser/autofill/autofill_download.h b/chrome/browser/autofill/autofill_download.h index fc24c92..a3a66fd 100644 --- a/chrome/browser/autofill/autofill_download.h +++ b/chrome/browser/autofill/autofill_download.h @@ -29,6 +29,7 @@ class AutoFillDownloadManager : public URLFetcher::Delegate { REQUEST_QUERY, REQUEST_UPLOAD, }; + // An interface used to notify clients of AutoFillDownloadManager. // Notifications are *not* guaranteed to be called. class Observer { diff --git a/chrome/browser/autofill/autofill_download_unittest.cc b/chrome/browser/autofill/autofill_download_unittest.cc index deb9b49..68173c6 100644 --- a/chrome/browser/autofill/autofill_download_unittest.cc +++ b/chrome/browser/autofill/autofill_download_unittest.cc @@ -101,37 +101,44 @@ TEST(AutoFillDownloadTest, QueryAndUploadTest) { ASCIIToUTF16("username"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"), ASCIIToUTF16("firstname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"), ASCIIToUTF16("email"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email2"), ASCIIToUTF16("email2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("password"), ASCIIToUTF16("password"), string16(), ASCIIToUTF16("password"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); FormStructure *form_structure = new FormStructure(form); ScopedVector<FormStructure> form_structures; @@ -142,22 +149,26 @@ TEST(AutoFillDownloadTest, QueryAndUploadTest) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("address2"), ASCIIToUTF16("address2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("city"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure = new FormStructure(form); form_structures.push_back(form_structure); diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc index 3d8f33c..8d14e75 100644 --- a/chrome/browser/autofill/autofill_manager.cc +++ b/chrome/browser/autofill/autofill_manager.cc @@ -5,7 +5,7 @@ #include "chrome/browser/autofill/autofill_manager.h" #include <limits> -#include <string> +#include <set> #include "app/l10n_util.h" #include "base/basictypes.h" @@ -16,6 +16,7 @@ #endif #include "chrome/browser/autofill/autofill_dialog.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/guid.h" #include "chrome/browser/prefs/pref_service.h" @@ -47,44 +48,83 @@ namespace { const double kAutoFillPositiveUploadRateDefaultValue = 0.01; const double kAutoFillNegativeUploadRateDefaultValue = 0.01; -// Size and offset of the prefix and suffix portions of phone numbers. -const int kAutoFillPhoneNumberPrefixOffset = 0; -const int kAutoFillPhoneNumberPrefixCount = 3; -const int kAutoFillPhoneNumberSuffixOffset = 3; -const int kAutoFillPhoneNumberSuffixCount = 4; - const string16::value_type kCreditCardPrefix[] = {'*',0}; const string16::value_type kLabelSeparator[] = {';',' ','*',0}; -// Removes duplicate elements whilst preserving original order of |elements| and -// |unique_ids|. -void RemoveDuplicateElements( - std::vector<string16>* elements, std::vector<int>* unique_ids) { - DCHECK_EQ(elements->size(), unique_ids->size()); - - std::vector<string16> elements_copy; +// Removes duplicate suggestions whilst preserving their original order. +void RemoveDuplicateSuggestions(std::vector<string16>* values, + std::vector<string16>* labels, + std::vector<string16>* icons, + std::vector<int>* unique_ids) { + DCHECK_EQ(values->size(), labels->size()); + DCHECK_EQ(values->size(), icons->size()); + DCHECK_EQ(values->size(), unique_ids->size()); + + std::set<std::pair<string16, string16> > seen_suggestions; + std::vector<string16> values_copy; + std::vector<string16> labels_copy; + std::vector<string16> icons_copy; std::vector<int> unique_ids_copy; - for (size_t i = 0; i < elements->size(); ++i) { - const string16& element = (*elements)[i]; - - bool unique = true; - for (std::vector<string16>::const_iterator copy_iter - = elements_copy.begin(); - copy_iter != elements_copy.end(); ++copy_iter) { - if (element == *copy_iter) { - unique = false; - break; - } - } - if (unique) { - elements_copy.push_back(element); + for (size_t i = 0; i < values->size(); ++i) { + const std::pair<string16, string16> suggestion((*values)[i], (*labels)[i]); + if (seen_suggestions.insert(suggestion).second) { + values_copy.push_back((*values)[i]); + labels_copy.push_back((*labels)[i]); + icons_copy.push_back((*icons)[i]); unique_ids_copy.push_back((*unique_ids)[i]); } } - elements->assign(elements_copy.begin(), elements_copy.end()); - unique_ids->assign(unique_ids_copy.begin(), unique_ids_copy.end()); + values->swap(values_copy); + labels->swap(labels_copy); + icons->swap(icons_copy); + unique_ids->swap(unique_ids_copy); +} + +// Precondition: |form_structure| and |form| should correspond to the same +// logical form. Returns true if the relevant portion of |form| is auto-filled. +// If |is_filling_credit_card|, the relevant portion is the credit card portion; +// otherwise it is the address and contact info portion. +bool FormIsAutoFilled(const FormStructure* form_structure, + const webkit_glue::FormData& form, + bool is_filling_credit_card) { + // TODO(isherman): It would be nice to share most of this code with the loop + // in |FillAutoFillFormData()|, but I don't see a particularly clean way to do + // that. + + // The list of fields in |form_structure| and |form.fields| often match + // directly and we can fill these corresponding fields; however, when the + // |form_structure| and |form.fields| do not match directly we search + // ahead in the |form_structure| for the matching field. + for (size_t i = 0, j = 0; + i < form_structure->field_count() && j < form.fields.size(); + j++) { + size_t k = i; + + // Search forward in the |form_structure| for a corresponding field. + while (k < form_structure->field_count() && + *form_structure->field(k) != form.fields[j]) { + k++; + } + + // If we didn't find a match, continue on to the next |form| field. + if (k >= form_structure->field_count()) + continue; + + AutoFillType autofill_type(form_structure->field(k)->type()); + bool is_credit_card_field = + autofill_type.group() == AutoFillType::CREDIT_CARD; + if (is_filling_credit_card == is_credit_card_field && + form.fields[j].is_autofilled()) + return true; + + // We found a matching field in the |form_structure| so we + // proceed to the next |form| field, and the next |form_structure|. + ++i; + } + + return false; } bool FormIsHTTPS(FormStructure* form) { @@ -160,8 +200,9 @@ void AutoFillManager::FormsSeen(const std::vector<FormData>& forms) { ParseForms(forms); } -bool AutoFillManager::GetAutoFillSuggestions(bool field_autofilled, +bool AutoFillManager::GetAutoFillSuggestions(const FormData& form, const FormField& field) { +<<<<<<< HEAD if (!IsAutoFillEnabled()) return false; @@ -182,45 +223,38 @@ bool AutoFillManager::GetAutoFillSuggestions(bool field_autofilled, // Loops through the cached FormStructures looking for the FormStructure that // contains |field| and the associated AutoFillFieldType. FormStructure* form = NULL; +======= + RenderViewHost* host = NULL; + FormStructure* form_structure = NULL; +>>>>>>> Chromium.org at 9.0.597.55 AutoFillField* autofill_field = NULL; - for (std::vector<FormStructure*>::iterator form_iter = - form_structures_.begin(); - form_iter != form_structures_.end() && !autofill_field; ++form_iter) { - form = *form_iter; - - // Don't send suggestions for forms that aren't auto-fillable. - if (!form->IsAutoFillable(false)) - continue; + if (!GetHost(personal_data_->profiles(), + personal_data_->credit_cards(), + &host) || + !FindCachedFormAndField(form, field, &form_structure, &autofill_field)) + return false; - for (std::vector<AutoFillField*>::const_iterator iter = form->begin(); - iter != form->end(); ++iter) { - // The field list is terminated with a NULL AutoFillField, so don't try to - // dereference it. - if (!*iter) - break; + DCHECK(host); + DCHECK(form_structure); + DCHECK(autofill_field); - if ((**iter) == field) { - autofill_field = *iter; - break; - } - } - } - - if (!autofill_field) + // Don't send suggestions for forms that aren't auto-fillable. + if (!form_structure->IsAutoFillable(false)) return false; std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; std::vector<int> unique_ids; - AutoFillType type(autofill_field->type()); - if (type.group() == AutoFillType::CREDIT_CARD) { + AutoFillType type(autofill_field->type()); + bool is_filling_credit_card = (type.group() == AutoFillType::CREDIT_CARD); + if (is_filling_credit_card) { GetCreditCardSuggestions( - form, field, type, &values, &labels, &icons, &unique_ids); + form_structure, field, type, &values, &labels, &icons, &unique_ids); } else { GetProfileSuggestions( - form, field, type, &values, &labels, &icons, &unique_ids); + form_structure, field, type, &values, &labels, &icons, &unique_ids); } DCHECK_EQ(values.size(), labels.size()); @@ -231,6 +265,7 @@ bool AutoFillManager::GetAutoFillSuggestions(bool field_autofilled, if (values.empty()) return false; +<<<<<<< HEAD #ifndef ANDROID // Don't provide AutoFill suggestions when AutoFill is disabled, but provide a // warning to the user. @@ -251,6 +286,18 @@ bool AutoFillManager::GetAutoFillSuggestions(bool field_autofilled, if (!FormIsHTTPS(form) && type.group() == AutoFillType::CREDIT_CARD) { values.assign( 1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION)); +======= + // Don't provide AutoFill suggestions when AutoFill is disabled, and don't + // provide credit card suggestions for non-HTTPS pages. However, provide a + // warning to the user in these cases. + int warning = 0; + if (!form_structure->IsAutoFillable(true)) + warning = IDS_AUTOFILL_WARNING_FORM_DISABLED; + else if (is_filling_credit_card && !FormIsHTTPS(form_structure)) + warning = IDS_AUTOFILL_WARNING_INSECURE_CONNECTION; + if (warning) { + values.assign(1, l10n_util::GetStringUTF16(warning)); +>>>>>>> Chromium.org at 9.0.597.55 labels.assign(1, string16()); icons.assign(1, string16()); unique_ids.assign(1, -1); @@ -260,29 +307,23 @@ bool AutoFillManager::GetAutoFillSuggestions(bool field_autofilled, #endif // If the form is auto-filled and the renderer is querying for suggestions, - // then the user is editing the value of a field. In this case, mimick - // autocomplete. In particular, don't display labels, as that information is - // redundant. In addition, remove duplicate values. - if (field_autofilled) { - RemoveDuplicateElements(&values, &unique_ids); - labels.resize(values.size()); - icons.resize(values.size()); - unique_ids.resize(values.size()); - - for (size_t i = 0; i < labels.size(); ++i) { - labels[i] = string16(); - icons[i] = string16(); - unique_ids[i] = 0; - } + // then the user is editing the value of a field. In this case, mimick + // autocomplete: don't display or icons, as that information is redundant. + if (FormIsAutoFilled(form_structure, form, is_filling_credit_card)) { + labels.assign(labels.size(), string16()); + icons.assign(icons.size(), string16()); } + RemoveDuplicateSuggestions(&values, &labels, &icons, &unique_ids); host->AutoFillSuggestionsReturned(values, labels, icons, unique_ids); return true; } bool AutoFillManager::FillAutoFillFormData(int query_id, const FormData& form, + const FormField& field, int unique_id) { +<<<<<<< HEAD if (!IsAutoFillEnabled()) return false; @@ -294,31 +335,20 @@ bool AutoFillManager::FillAutoFillFormData(int query_id, if (!host) return false; +======= +>>>>>>> Chromium.org at 9.0.597.55 const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles(); const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards(); - - // No data to return if the profiles are empty. - if (profiles.empty() && credit_cards.empty()) - return false; - - // Find the FormStructure that corresponds to |form|. - FormData result = form; + RenderViewHost* host = NULL; FormStructure* form_structure = NULL; - for (std::vector<FormStructure*>::const_iterator iter = - form_structures_.begin(); - iter != form_structures_.end(); ++iter) { - if (**iter == form) { - form_structure = *iter; - break; - } - } - - if (!form_structure) + AutoFillField* autofill_field = NULL; + if (!GetHost(profiles, credit_cards, &host) || + !FindCachedFormAndField(form, field, &form_structure, &autofill_field)) return false; - // No data to return if there are no auto-fillable fields. - if (!form_structure->autofill_count()) - return false; + DCHECK(host); + DCHECK(form_structure); + DCHECK(autofill_field); // Unpack the |unique_id| into component parts. std::string cc_guid; @@ -355,6 +385,30 @@ bool AutoFillManager::FillAutoFillFormData(int query_id, if (!profile && !credit_card) return false; + FormData result = form; + + // If the form is auto-filled, we should fill |field| but not the rest of the + // form. + if (FormIsAutoFilled(form_structure, form, (credit_card != NULL))) { + for (std::vector<FormField>::iterator iter = result.fields.begin(); + iter != result.fields.end(); ++iter) { + if ((*iter) == field) { + AutoFillType autofill_type(autofill_field->type()); + if (credit_card && + autofill_type.group() == AutoFillType::CREDIT_CARD) { + FillCreditCardFormField(credit_card, autofill_type, &(*iter)); + } else if (profile && + autofill_type.group() != AutoFillType::CREDIT_CARD) { + FillFormField(profile, autofill_type, &(*iter)); + } + break; + } + } + + host->AutoFillFormDataFilled(query_id, result); + return true; + } + // The list of fields in |form_structure| and |result.fields| often match // directly and we can fill these corresponding fields; however, when the // |form_structure| and |result.fields| do not match directly we search @@ -382,7 +436,8 @@ bool AutoFillManager::FillAutoFillFormData(int query_id, if (credit_card && autofill_type.group() == AutoFillType::CREDIT_CARD) { FillCreditCardFormField(credit_card, autofill_type, &result.fields[j]); - } else if (profile) { + } else if (profile && + autofill_type.group() != AutoFillType::CREDIT_CARD) { FillFormField(profile, autofill_type, &result.fields[j]); } @@ -532,6 +587,67 @@ AutoFillManager::AutoFillManager(TabContents* tab_contents, DCHECK(tab_contents); } +bool AutoFillManager::GetHost(const std::vector<AutoFillProfile*>& profiles, + const std::vector<CreditCard*>& credit_cards, + RenderViewHost** host) { + if (!IsAutoFillEnabled()) + return false; + + // No autofill data to return if the profiles are empty. + if (profiles.empty() && credit_cards.empty()) + return false; + + *host = tab_contents_->render_view_host(); + if (!(*host)) + return false; + + return true; +} + +bool AutoFillManager::FindCachedFormAndField(const FormData& form, + const FormField& field, + FormStructure** form_structure, + AutoFillField** autofill_field) { + // Find the FormStructure that corresponds to |form|. + *form_structure = NULL; + for (std::vector<FormStructure*>::const_iterator iter = + form_structures_.begin(); + iter != form_structures_.end(); ++iter) { + if (**iter == form) { + *form_structure = *iter; + break; + } + } + + if (!(*form_structure)) + return false; + + // No data to return if there are no auto-fillable fields. + if (!(*form_structure)->autofill_count()) + return false; + + // Find the AutoFillField that corresponds to |field|. + *autofill_field = NULL; + for (std::vector<AutoFillField*>::const_iterator iter = + (*form_structure)->begin(); + iter != (*form_structure)->end(); ++iter) { + // The field list is terminated with a NULL AutoFillField, so don't try to + // dereference it. + if (!*iter) + break; + + if ((**iter) == field) { + *autofill_field = *iter; + break; + } + } + + if (!(*autofill_field)) + return false; + + return true; +} + void AutoFillManager::GetProfileSuggestions(FormStructure* form, const FormField& field, AutoFillType type, @@ -567,7 +683,7 @@ void AutoFillManager::GetProfileSuggestions(FormStructure* form, form_fields.push_back((*iter)->type()); } - AutoFillProfile::CreateInferredLabels(&matched_profiles, labels, 0, + AutoFillProfile::CreateInferredLabels(&matched_profiles, labels, 1, type.field_type(), &form_fields); // No icons for profile suggestions. @@ -605,6 +721,7 @@ void AutoFillManager::FillCreditCardFormField(const CreditCard* credit_card, AutoFillType type, webkit_glue::FormField* field) { DCHECK(credit_card); + DCHECK(type.group() == AutoFillType::CREDIT_CARD); DCHECK(field); if (field->form_control_type() == ASCIIToUTF16("select-one")) @@ -617,6 +734,7 @@ void AutoFillManager::FillFormField(const AutoFillProfile* profile, AutoFillType type, webkit_glue::FormField* field) { DCHECK(profile); + DCHECK(type.group() != AutoFillType::CREDIT_CARD); DCHECK(field); if (type.subgroup() == AutoFillType::PHONE_NUMBER) { @@ -635,16 +753,17 @@ void AutoFillManager::FillPhoneNumberField(const AutoFillProfile* profile, // matches the "prefix" or "suffix" sizes and fill accordingly. string16 number = profile->GetFieldText(AutoFillType(PHONE_HOME_NUMBER)); bool has_valid_suffix_and_prefix = (number.length() == - (kAutoFillPhoneNumberPrefixCount + kAutoFillPhoneNumberSuffixCount)); + static_cast<size_t>(PhoneNumber::kPrefixLength + + PhoneNumber::kSuffixLength)); if (has_valid_suffix_and_prefix && - field->size() == kAutoFillPhoneNumberPrefixCount) { - number = number.substr(kAutoFillPhoneNumberPrefixOffset, - kAutoFillPhoneNumberPrefixCount); + field->max_length() == PhoneNumber::kPrefixLength) { + number = number.substr(PhoneNumber::kPrefixOffset, + PhoneNumber::kPrefixLength); field->set_value(number); } else if (has_valid_suffix_and_prefix && - field->size() == kAutoFillPhoneNumberSuffixCount) { - number = number.substr(kAutoFillPhoneNumberSuffixOffset, - kAutoFillPhoneNumberSuffixCount); + field->max_length() == PhoneNumber::kSuffixLength) { + number = number.substr(PhoneNumber::kSuffixOffset, + PhoneNumber::kSuffixLength); field->set_value(number); } else { field->set_value(number); diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h index 2037a11..498a704 100644 --- a/chrome/browser/autofill/autofill_manager.h +++ b/chrome/browser/autofill/autofill_manager.h @@ -6,9 +6,9 @@ #define CHROME_BROWSER_AUTOFILL_AUTOFILL_MANAGER_H_ #pragma once -#include <vector> -#include <string> #include <list> +#include <string> +#include <vector> #include "base/gtest_prod_util.h" #include "base/scoped_ptr.h" @@ -57,10 +57,11 @@ class AutoFillManager : // RenderViewHostDelegate::AutoFill implementation: virtual void FormSubmitted(const webkit_glue::FormData& form); virtual void FormsSeen(const std::vector<webkit_glue::FormData>& forms); - virtual bool GetAutoFillSuggestions(bool field_autofilled, + virtual bool GetAutoFillSuggestions(const webkit_glue::FormData& form, const webkit_glue::FormField& field); virtual bool FillAutoFillFormData(int query_id, const webkit_glue::FormData& form, + const webkit_glue::FormField& field, int unique_id); virtual void ShowAutoFillDialog(); @@ -102,7 +103,32 @@ class AutoFillManager : personal_data_ = personal_data; } + // Maps GUIDs to and from IDs that are used to identify profiles and credit + // cards sent to and from the renderer process. + virtual int GUIDToID(const std::string& guid); + virtual const std::string IDToGUID(int id); + + // Methods for packing and unpacking credit card and profile IDs for sending + // and receiving to and from the renderer process. + int PackGUIDs(const std::string& cc_guid, const std::string& profile_guid); + void UnpackGUIDs(int id, std::string* cc_guid, std::string* profile_guid); + private: + // Fills |host| with the RenderViewHost for this tab. + // Returns false if AutoFill is disabled or if the host is unavailable. + bool GetHost(const std::vector<AutoFillProfile*>& profiles, + const std::vector<CreditCard*>& credit_cards, + RenderViewHost** host) WARN_UNUSED_RESULT; + + // Fills |form_structure| and |autofill_field| with the cached elements + // corresponding to |form| and |field|. Returns false if the cached elements + // were not found. + bool FindCachedFormAndField( + const webkit_glue::FormData& form, + const webkit_glue::FormField& field, + FormStructure** form_structure, + AutoFillField** autofill_field) WARN_UNUSED_RESULT; + // Returns a list of values from the stored profiles that match |type| and the // value of |field| and returns the labels of the matching profiles. |labels| // is filled with the Profile label. @@ -143,16 +169,6 @@ class AutoFillManager : // Parses the forms using heuristic matching and querying the AutoFill server. void ParseForms(const std::vector<webkit_glue::FormData>& forms); - // Methods for packing and unpacking credit card and profile IDs for sending - // and receiving to and from the renderer process. - int PackGUIDs(const std::string& cc_guid, const std::string& profile_guid); - void UnpackGUIDs(int id, std::string* cc_guid, std::string* profile_guid); - - // Maps GUIDs to and from IDs that are used to identify profiles and credit - // cards sent to and from the renderer process. - int GUIDToID(const std::string& guid); - const std::string IDToGUID(int id); - // The following function is meant to be called from unit-test only. void set_disable_download_manager_requests(bool value) { disable_download_manager_requests_ = value; @@ -197,10 +213,12 @@ class AutoFillManager : std::map<std::string, int> guid_id_map_; std::map<int, std::string> id_guid_map_; + friend class FormStructureBrowserTest; friend class TestAutoFillManager; FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillCreditCardForm); FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillAddressForm); FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillAddressAndCreditCardForm); + FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillAutoFilledForm); FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FillPhoneNumber); FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FormChangesRemoveField); FRIEND_TEST_ALL_PREFIXES(AutoFillManagerTest, FormChangesAddField); diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc index 182148d..06af660 100644 --- a/chrome/browser/autofill/autofill_manager_unittest.cc +++ b/chrome/browser/autofill/autofill_manager_unittest.cc @@ -8,7 +8,9 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/scoped_vector.h" +#include "base/string_number_conversions.h" #include "base/string16.h" +#include "base/stringprintf.h" #include "base/tuple.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_common_test.h" @@ -30,6 +32,13 @@ #include "webkit/glue/form_field.h" using webkit_glue::FormData; +using webkit_glue::FormField; + +namespace { + +// The page ID sent to the AutoFillManager from the RenderView, used to send +// an IPC message back to the renderer. +const int kDefaultPageID = 137; typedef Tuple5<int, std::vector<string16>, @@ -51,8 +60,17 @@ class TestPersonalDataManager : public PersonalDataManager { AutoFillProfile* GetLabeledProfile(const char* label) { for (std::vector<AutoFillProfile *>::iterator it = web_profiles_.begin(); it != web_profiles_.end(); ++it) { - if (!(*it)->Label().compare(ASCIIToUTF16(label))) - return *it; + if (!(*it)->Label().compare(ASCIIToUTF16(label))) + return *it; + } + return NULL; + } + + CreditCard* GetLabeledCreditCard(const char* label) { + for (std::vector<CreditCard *>::iterator it = credit_cards_.begin(); + it != credit_cards_.end(); ++it) { + if (!(*it)->Label().compare(ASCIIToUTF16(label))) + return *it; } return NULL; } @@ -116,40 +134,6 @@ class TestPersonalDataManager : public PersonalDataManager { DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager); }; -class TestAutoFillManager : public AutoFillManager { - public: - TestAutoFillManager(TabContents* tab_contents, - TestPersonalDataManager* personal_manager) - : AutoFillManager(tab_contents, NULL), - autofill_enabled_(true) { - test_personal_data_ = personal_manager; - set_personal_data_manager(personal_manager); - // Download manager requests are disabled for purposes of this unit-test. - // These request are tested in autofill_download_unittest.cc. - set_disable_download_manager_requests(true); - } - - virtual bool IsAutoFillEnabled() const { return autofill_enabled_; } - - void set_autofill_enabled(bool autofill_enabled) { - autofill_enabled_ = autofill_enabled; - } - - AutoFillProfile* GetLabeledProfile(const char* label) { - return test_personal_data_->GetLabeledProfile(label); - } - - void AddProfile(AutoFillProfile* profile) { - test_personal_data_->AddProfile(profile); - } - - private: - TestPersonalDataManager* test_personal_data_; - bool autofill_enabled_; - - DISALLOW_COPY_AND_ASSIGN(TestAutoFillManager); -}; - // Populates |form| with data corresponding to a simple address form. // Note that this actually appends fields to the form data, which can be useful // for building up more complex test forms. @@ -160,7 +144,7 @@ void CreateTestAddressFormData(FormData* form) { form->action = GURL("http://myform.com/submit.html"); form->user_submitted = true; - webkit_glue::FormField field; + FormField field; autofill_test::CreateTestFormField( "First Name", "firstname", "", "text", &field); form->fields.push_back(field); @@ -192,6 +176,9 @@ void CreateTestAddressFormData(FormData* form) { "Phone Number", "phonenumber", "", "text", &field); form->fields.push_back(field); autofill_test::CreateTestFormField( + "Fax", "fax", "", "text", &field); + form->fields.push_back(field); + autofill_test::CreateTestFormField( "Email", "email", "", "text", &field); form->fields.push_back(field); } @@ -211,7 +198,7 @@ void CreateTestCreditCardFormData(FormData* form, bool is_https) { } form->user_submitted = true; - webkit_glue::FormField field; + FormField field; autofill_test::CreateTestFormField( "Name on Card", "nameoncard", "", "text", &field); form->fields.push_back(field); @@ -226,6 +213,218 @@ void CreateTestCreditCardFormData(FormData* form, bool is_https) { form->fields.push_back(field); } +void ExpectSuggestions(int page_id, + const std::vector<string16>& values, + const std::vector<string16>& labels, + const std::vector<string16>& icons, + const std::vector<int>& unique_ids, + int expected_page_id, + size_t expected_num_suggestions, + const string16 expected_values[], + const string16 expected_labels[], + const string16 expected_icons[], + const int expected_unique_ids[]) { + EXPECT_EQ(expected_page_id, page_id); + ASSERT_EQ(expected_num_suggestions, values.size()); + ASSERT_EQ(expected_num_suggestions, labels.size()); + ASSERT_EQ(expected_num_suggestions, icons.size()); + ASSERT_EQ(expected_num_suggestions, unique_ids.size()); + for (size_t i = 0; i < expected_num_suggestions; ++i) { + SCOPED_TRACE(StringPrintf("i: %" PRIuS, i)); + EXPECT_EQ(expected_values[i], values[i]); + EXPECT_EQ(expected_labels[i], labels[i]); + EXPECT_EQ(expected_icons[i], icons[i]); + EXPECT_EQ(expected_unique_ids[i], unique_ids[i]); + } +} + +// Verifies that the |filled_form| has been filled with the given data. +// Verifies address fields if |has_address_fields| is true, and verifies +// credit card fields if |has_credit_card_fields| is true. Verifies both if both +// are true. +void ExpectFilledForm(int page_id, + const FormData& filled_form, + int expected_page_id, + const char* first, + const char* middle, + const char* last, + const char* address1, + const char* address2, + const char* city, + const char* state, + const char* postal_code, + const char* country, + const char* phone, + const char* fax, + const char* email, + const char* name_on_card, + const char* card_number, + const char* expiration_month, + const char* expiration_year, + bool has_address_fields, + bool has_credit_card_fields) { + // The number of fields in the address and credit card forms created above. + const size_t kAddressFormSize = 12; + const size_t kCreditCardFormSize = 4; + + EXPECT_EQ(expected_page_id, page_id); + EXPECT_EQ(ASCIIToUTF16("MyForm"), filled_form.name); + EXPECT_EQ(ASCIIToUTF16("POST"), filled_form.method); + if (has_credit_card_fields) { + EXPECT_EQ(GURL("https://myform.com/form.html"), filled_form.origin); + EXPECT_EQ(GURL("https://myform.com/submit.html"), filled_form.action); + } else { + EXPECT_EQ(GURL("http://myform.com/form.html"), filled_form.origin); + EXPECT_EQ(GURL("http://myform.com/submit.html"), filled_form.action); + } + EXPECT_TRUE(filled_form.user_submitted); + + size_t form_size = 0; + if (has_address_fields) + form_size += kAddressFormSize; + if (has_credit_card_fields) + form_size += kCreditCardFormSize; + ASSERT_EQ(form_size, filled_form.fields.size()); + + FormField field; + if (has_address_fields) { + autofill_test::CreateTestFormField( + "First Name", "firstname", first, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[0])); + autofill_test::CreateTestFormField( + "Middle Name", "middlename", middle, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[1])); + autofill_test::CreateTestFormField( + "Last Name", "lastname", last, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[2])); + autofill_test::CreateTestFormField( + "Address Line 1", "addr1", address1, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[3])); + autofill_test::CreateTestFormField( + "Address Line 2", "addr2", address2, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[4])); + autofill_test::CreateTestFormField( + "City", "city", city, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[5])); + autofill_test::CreateTestFormField( + "State", "state", state, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[6])); + autofill_test::CreateTestFormField( + "Postal Code", "zipcode", postal_code, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[7])); + autofill_test::CreateTestFormField( + "Country", "country", country, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[8])); + autofill_test::CreateTestFormField( + "Phone Number", "phonenumber", phone, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[9])); + autofill_test::CreateTestFormField( + "Fax", "fax", fax, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[10])); + autofill_test::CreateTestFormField( + "Email", "email", email, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[11])); + } + + if (has_credit_card_fields) { + size_t offset = has_address_fields? kAddressFormSize : 0; + autofill_test::CreateTestFormField( + "Name on Card", "nameoncard", name_on_card, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 0])); + autofill_test::CreateTestFormField( + "Card Number", "cardnumber", card_number, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 1])); + autofill_test::CreateTestFormField( + "Expiration Date", "ccmonth", expiration_month, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 2])); + autofill_test::CreateTestFormField( + "", "ccyear", expiration_year, "text", &field); + EXPECT_TRUE(field.StrictlyEqualsHack(filled_form.fields[offset + 3])); + } +} + +void ExpectFilledAddressFormElvis(int page_id, + const FormData& filled_form, + int expected_page_id, + bool has_credit_card_fields) { + ExpectFilledForm(page_id, filled_form, expected_page_id, "Elvis", "Aaron", + "Presley", "3734 Elvis Presley Blvd.", "Apt. 10", "Memphis", + "Tennessee", "38116", "USA", "12345678901", "", + "theking@gmail.com", "", "", "", "", true, + has_credit_card_fields); +} + +void ExpectFilledCreditCardFormElvis(int page_id, + const FormData& filled_form, + int expected_page_id, + bool has_address_fields) { + ExpectFilledForm(page_id, filled_form, expected_page_id, + "", "", "", "", "", "", "", "", "", "", "", "", + "Elvis Presley", "4234567890123456", "04", "2012", + has_address_fields, true); +} + +} // namespace + +class TestAutoFillManager : public AutoFillManager { + public: + TestAutoFillManager(TabContents* tab_contents, + TestPersonalDataManager* personal_manager) + : AutoFillManager(tab_contents, NULL), + autofill_enabled_(true) { + test_personal_data_ = personal_manager; + set_personal_data_manager(personal_manager); + // Download manager requests are disabled for purposes of this unit test. + // These requests are tested in autofill_download_unittest.cc. + set_disable_download_manager_requests(true); + } + + virtual bool IsAutoFillEnabled() const { return autofill_enabled_; } + + void set_autofill_enabled(bool autofill_enabled) { + autofill_enabled_ = autofill_enabled; + } + + AutoFillProfile* GetLabeledProfile(const char* label) { + return test_personal_data_->GetLabeledProfile(label); + } + + CreditCard* GetLabeledCreditCard(const char* label) { + return test_personal_data_->GetLabeledCreditCard(label); + } + + void AddProfile(AutoFillProfile* profile) { + test_personal_data_->AddProfile(profile); + } + + int GetPackedCreditCardID(int credit_card_id) { + return PackGUIDs(IDToGUID(credit_card_id), std::string()); + } + + virtual int GUIDToID(const std::string& guid) OVERRIDE { + if (guid.empty()) + return 0; + + int id; + EXPECT_TRUE(base::StringToInt(guid.substr(guid.rfind("-") + 1), &id)); + return id; + } + + virtual const std::string IDToGUID(int id) OVERRIDE { + EXPECT_TRUE(id >= 0); + if (id <= 0) + return std::string(); + + return base::StringPrintf("00000000-0000-0000-0000-%012d", id); + } + + private: + TestPersonalDataManager* test_personal_data_; + bool autofill_enabled_; + + DISALLOW_COPY_AND_ASSIGN(TestAutoFillManager); +}; + class AutoFillManagerTest : public RenderViewHostTestHarness { public: AutoFillManagerTest() {} @@ -248,7 +447,8 @@ class AutoFillManagerTest : public RenderViewHostTestHarness { bool GetAutoFillSuggestionsMessage(int* page_id, std::vector<string16>* values, std::vector<string16>* labels, - std::vector<string16>* icons) { + std::vector<string16>* icons, + std::vector<int>* unique_ids) { const uint32 kMsgID = ViewMsg_AutoFillSuggestionsReturned::ID; const IPC::Message* message = process()->sink().GetFirstMessageMatching(kMsgID); @@ -265,6 +465,8 @@ class AutoFillManagerTest : public RenderViewHostTestHarness { *labels = autofill_param.c; if (icons) *icons = autofill_param.d; + if (unique_ids) + *unique_ids = autofill_param.e; return true; } @@ -294,23 +496,15 @@ class AutoFillManagerTest : public RenderViewHostTestHarness { // Test that we return all address profile suggestions when all form fields are // empty. TEST_F(AutoFillManagerTest, GetProfileSuggestionsEmptyValue) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -321,42 +515,41 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsEmptyValue) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]); - EXPECT_EQ(ASCIIToUTF16("Charles"), values[1]); - ASSERT_EQ(2U, labels.size()); - // Inferred labels now include full first relevant field, which in this case - // the address #1. - EXPECT_EQ(ASCIIToUTF16("3734 Elvis Presley Blvd."), labels[0]); - EXPECT_EQ(ASCIIToUTF16("123 Apple St."), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("Elvis"), + ASCIIToUTF16("Charles") + }; + // Inferred labels include full first relevant field, which in this case is + // the address line 1. + string16 expected_labels[] = { + ASCIIToUTF16("3734 Elvis Presley Blvd."), + ASCIIToUTF16("123 Apple St.") + }; + string16 expected_icons[] = {string16(), string16()}; + int expected_unique_ids[] = {1, 2}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we return only matching address profile suggestions when the // selected form field has been partially filled out. TEST_F(AutoFillManagerTest, GetProfileSuggestionsMatchCharacter) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "E", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + FormField field; + autofill_test::CreateTestFormField("First Name", "firstname", "E", "text", + &field); + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -367,19 +560,22 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsMatchCharacter) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(1U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]); - ASSERT_EQ(1U, labels.size()); - EXPECT_EQ(ASCIIToUTF16("3734 Elvis Presley Blvd."), labels[0]); - ASSERT_EQ(1U, icons.size()); - EXPECT_EQ(string16(), icons[0]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = {ASCIIToUTF16("Elvis")}; + string16 expected_labels[] = {ASCIIToUTF16("3734 Elvis Presley Blvd.")}; + string16 expected_icons[] = {string16()}; + int expected_unique_ids[] = {1}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we return no suggestions when the form has no relevant fields. TEST_F(AutoFillManagerTest, GetProfileSuggestionsUnknownFields) { + // Set up our form data. FormData form; form.name = ASCIIToUTF16("MyForm"); form.method = ASCIIToUTF16("POST"); @@ -387,81 +583,99 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsUnknownFields) { form.action = GURL("http://myform.com/submit.html"); form.user_submitted = true; - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "Username", "username", "", "text", &field); + FormField field; + autofill_test::CreateTestFormField("Username", "username", "", "text", + &field); form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Password", "password", "", "password", &field); + autofill_test::CreateTestFormField("Password", "password", "", "password", + &field); form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Quest", "quest", "", "quest", &field); + autofill_test::CreateTestFormField("Quest", "quest", "", "quest", &field); form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Color", "color", "", "text", &field); + autofill_test::CreateTestFormField("Color", "color", "", "text", &field); form.fields.push_back(field); - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field)); +} - autofill_test::CreateTestFormField( - "Username", "username", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_FALSE( - autofill_manager_->GetAutoFillSuggestions(false, field)); +// Test that we cull duplicate profile suggestions. +TEST_F(AutoFillManagerTest, GetProfileSuggestionsWithDuplicates) { + // Set up our form data. + FormData form; + CreateTestAddressFormData(&form); + std::vector<FormData> forms(1, form); + autofill_manager_->FormsSeen(forms); + + // Add a duplicate profile. + AutoFillProfile* duplicate_profile = static_cast<AutoFillProfile*>( + autofill_manager_->GetLabeledProfile("Home")->Clone()); + autofill_manager_->AddProfile(duplicate_profile); + + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); + + // No suggestions provided, so send an empty vector as the results. + // This triggers the combined message send. + rvh()->AutocompleteSuggestionsReturned(std::vector<string16>()); + + // Test that we sent the right message to the renderer. + int page_id = 0; + std::vector<string16> values; + std::vector<string16> labels; + std::vector<string16> icons; + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("Elvis"), + ASCIIToUTF16("Charles") + }; + string16 expected_labels[] = { + ASCIIToUTF16("3734 Elvis Presley Blvd."), + ASCIIToUTF16("123 Apple St.") + }; + string16 expected_icons[] = {string16(), string16()}; + int expected_unique_ids[] = {1, 2}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we return no suggestions when autofill is disabled. TEST_F(AutoFillManagerTest, GetProfileSuggestionsAutofillDisabledByUser) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); // Disable AutoFill. autofill_manager_->set_autofill_enabled(false); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field)); } // Test that we return a warning explaining that autofill suggestions are // unavailable when the form method is GET rather than POST. TEST_F(AutoFillManagerTest, GetProfileSuggestionsMethodGet) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); form.method = ASCIIToUTF16("GET"); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -472,71 +686,64 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsMethodGet) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(1U, values.size()); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED), - values[0]); - ASSERT_EQ(1U, labels.size()); - EXPECT_EQ(string16(), labels[0]); - ASSERT_EQ(1U, icons.size()); - EXPECT_EQ(string16(), icons[0]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED) + }; + string16 expected_labels[] = {string16()}; + string16 expected_icons[] = {string16()}; + int expected_unique_ids[] = {-1}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); // Now add some Autocomplete suggestions. We should return the autocomplete // suggestions and the warning; these will be culled by the renderer. process()->sink().ClearMessages(); const int kPageID2 = 2; rvh()->ResetAutoFillState(kPageID2); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); std::vector<string16> suggestions; suggestions.push_back(ASCIIToUTF16("Jay")); suggestions.push_back(ASCIIToUTF16("Jason")); rvh()->AutocompleteSuggestionsReturned(suggestions); - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID2, page_id); - ASSERT_EQ(3U, values.size()); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED), - values[0]); - EXPECT_EQ(ASCIIToUTF16("Jay"), values[1]); - EXPECT_EQ(ASCIIToUTF16("Jason"), values[2]); - ASSERT_EQ(3U, labels.size()); - EXPECT_EQ(string16(), labels[0]); - EXPECT_EQ(string16(), labels[1]); - EXPECT_EQ(string16(), labels[2]); - ASSERT_EQ(3U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); - EXPECT_EQ(string16(), icons[2]); + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values2[] = { + l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED), + ASCIIToUTF16("Jay"), + ASCIIToUTF16("Jason") + }; + string16 expected_labels2[] = {string16(), string16(), string16()}; + string16 expected_icons2[] = {string16(), string16(), string16()}; + int expected_unique_ids2[] = {-1, 0, 0}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kPageID2, arraysize(expected_values2), expected_values2, + expected_labels2, expected_icons2, expected_unique_ids2); // Now clear the test profiles and try again -- we shouldn't return a warning. test_personal_data_->ClearAutoFillProfiles(); - EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field)); } // Test that we return all credit card profile suggestions when all form fields // are empty. TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsEmptyValue) { + // Set up our form data. FormData form; CreateTestCreditCardFormData(&form, true); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "Card Number", "cardnumber", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + FormField field = form.fields[1]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -547,40 +754,42 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsEmptyValue) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("************3456"), values[0]); - EXPECT_EQ(ASCIIToUTF16("************8765"), values[1]); - ASSERT_EQ(2U, labels.size()); - EXPECT_EQ(ASCIIToUTF16("*3456"), labels[0]); - EXPECT_EQ(ASCIIToUTF16("*8765"), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(ASCIIToUTF16("visaCC"), icons[0]); - EXPECT_EQ(ASCIIToUTF16("masterCardCC"), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("************3456"), + ASCIIToUTF16("************8765") + }; + string16 expected_labels[] = {ASCIIToUTF16("*3456"), ASCIIToUTF16("*8765")}; + string16 expected_icons[] = { + ASCIIToUTF16("visaCC"), + ASCIIToUTF16("masterCardCC") + }; + int expected_unique_ids[] = { + autofill_manager_->GetPackedCreditCardID(4), + autofill_manager_->GetPackedCreditCardID(5) + }; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we return only matching credit card profile suggestions when the // selected form field has been partially filled out. TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsMatchCharacter) { + // Set up our form data. FormData form; CreateTestCreditCardFormData(&form, true); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; + FormField field; autofill_test::CreateTestFormField( "Card Number", "cardnumber", "4", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -591,37 +800,31 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsMatchCharacter) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(1U, values.size()); - EXPECT_EQ(ASCIIToUTF16("************3456"), values[0]); - ASSERT_EQ(1U, labels.size()); - EXPECT_EQ(ASCIIToUTF16("*3456"), labels[0]); - ASSERT_EQ(1U, icons.size()); - EXPECT_EQ(ASCIIToUTF16("visaCC"), icons[0]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = {ASCIIToUTF16("************3456")}; + string16 expected_labels[] = {ASCIIToUTF16("*3456")}; + string16 expected_icons[] = {ASCIIToUTF16("visaCC")}; + int expected_unique_ids[] = {autofill_manager_->GetPackedCreditCardID(4)}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we return credit card profile suggestions when the selected form // field is not the credit card number field. TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonCCNumber) { + // Set up our form data. FormData form; CreateTestCreditCardFormData(&form, true); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "Name on Card", "nameoncard", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -632,40 +835,40 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonCCNumber) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis Presley"), values[0]); - EXPECT_EQ(ASCIIToUTF16("Buddy Holly"), values[1]); - ASSERT_EQ(2U, labels.size()); - EXPECT_EQ(ASCIIToUTF16("*3456"), labels[0]); - EXPECT_EQ(ASCIIToUTF16("*8765"), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(ASCIIToUTF16("visaCC"), icons[0]); - EXPECT_EQ(ASCIIToUTF16("masterCardCC"), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("Elvis Presley"), + ASCIIToUTF16("Buddy Holly") + }; + string16 expected_labels[] = {ASCIIToUTF16("*3456"), ASCIIToUTF16("*8765")}; + string16 expected_icons[] = { + ASCIIToUTF16("visaCC"), + ASCIIToUTF16("masterCardCC") + }; + int expected_unique_ids[] = { + autofill_manager_->GetPackedCreditCardID(4), + autofill_manager_->GetPackedCreditCardID(5) + }; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we return a warning explaining that credit card profile suggestions // are unavailable when the form is not https. TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonHTTPS) { + // Set up our form data. FormData form; CreateTestCreditCardFormData(&form, false); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "Card Number", "cardnumber", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -676,71 +879,63 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonHTTPS) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(1U, values.size()); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION), - values[0]); - ASSERT_EQ(1U, labels.size()); - EXPECT_EQ(string16(), labels[0]); - ASSERT_EQ(1U, icons.size()); - EXPECT_EQ(string16(), icons[0]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION) + }; + string16 expected_labels[] = {string16()}; + string16 expected_icons[] = {string16()}; + int expected_unique_ids[] = {-1}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); // Now add some Autocomplete suggestions. We should show the autocomplete // suggestions and the warning. process()->sink().ClearMessages(); const int kPageID2 = 2; rvh()->ResetAutoFillState(kPageID2); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); std::vector<string16> suggestions; suggestions.push_back(ASCIIToUTF16("Jay")); suggestions.push_back(ASCIIToUTF16("Jason")); rvh()->AutocompleteSuggestionsReturned(suggestions); - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID2, page_id); - ASSERT_EQ(3U, values.size()); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION), - values[0]); - EXPECT_EQ(ASCIIToUTF16("Jay"), values[1]); - EXPECT_EQ(ASCIIToUTF16("Jason"), values[2]); - ASSERT_EQ(3U, labels.size()); - EXPECT_EQ(string16(), labels[0]); - EXPECT_EQ(string16(), labels[1]); - EXPECT_EQ(string16(), labels[2]); - ASSERT_EQ(3U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); - EXPECT_EQ(string16(), icons[2]); + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + string16 expected_values2[] = { + l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION), + ASCIIToUTF16("Jay"), + ASCIIToUTF16("Jason") + }; + string16 expected_labels2[] = {string16(), string16(), string16()}; + string16 expected_icons2[] = {string16(), string16(), string16()}; + int expected_unique_ids2[] = {-1, 0, 0}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kPageID2, arraysize(expected_values2), expected_values2, + expected_labels2, expected_icons2, expected_unique_ids2); // Clear the test credit cards and try again -- we shouldn't return a warning. test_personal_data_->ClearCreditCards(); - EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field)); } // Test that we return profile and credit card suggestions for combined forms. TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestions) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); CreateTestCreditCardFormData(&form, true); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + FormField field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -751,26 +946,30 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestions) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]); - EXPECT_EQ(ASCIIToUTF16("Charles"), values[1]); - ASSERT_EQ(2U, labels.size()); - // Inferred labels now include full first relevant field, which in this case - // the address #1. - EXPECT_EQ(ASCIIToUTF16("3734 Elvis Presley Blvd."), labels[0]); - EXPECT_EQ(ASCIIToUTF16("123 Apple St."), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("Elvis"), + ASCIIToUTF16("Charles") + }; + string16 expected_labels[] = { + ASCIIToUTF16("3734 Elvis Presley Blvd."), + ASCIIToUTF16("123 Apple St.") + }; + string16 expected_icons[] = {string16(), string16()}; + int expected_unique_ids[] = {1, 2}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); process()->sink().ClearMessages(); + const int kPageID2 = 2; autofill_test::CreateTestFormField( "Card Number", "cardnumber", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + rvh()->ResetAutoFillState(kPageID2); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -778,18 +977,25 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestions) { // Test that we sent the credit card suggestions to the renderer. page_id = 0; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("************3456"), values[0]); - EXPECT_EQ(ASCIIToUTF16("************8765"), values[1]); - ASSERT_EQ(2U, labels.size()); - EXPECT_EQ(ASCIIToUTF16("*3456"), labels[0]); - EXPECT_EQ(ASCIIToUTF16("*8765"), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(ASCIIToUTF16("visaCC"), icons[0]); - EXPECT_EQ(ASCIIToUTF16("masterCardCC"), icons[1]); + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values2[] = { + ASCIIToUTF16("************3456"), + ASCIIToUTF16("************8765") + }; + string16 expected_labels2[] = {ASCIIToUTF16("*3456"), ASCIIToUTF16("*8765")}; + string16 expected_icons2[] = { + ASCIIToUTF16("visaCC"), + ASCIIToUTF16("masterCardCC") + }; + int expected_unique_ids2[] = { + autofill_manager_->GetPackedCreditCardID(4), + autofill_manager_->GetPackedCreditCardID(5) + }; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kPageID2, arraysize(expected_values2), expected_values2, + expected_labels2, expected_icons2, expected_unique_ids2); } // Test that for non-https forms with both address and credit card fields, we @@ -797,24 +1003,16 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestions) { // should return a warning explaining that credit card profile suggestions are // unavailable when the form is not https. TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestionsNonHttps) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); CreateTestCreditCardFormData(&form, false); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + FormField field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -825,72 +1023,72 @@ TEST_F(AutoFillManagerTest, GetAddressAndCreditCardSuggestionsNonHttps) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]); - EXPECT_EQ(ASCIIToUTF16("Charles"), values[1]); - ASSERT_EQ(2U, labels.size()); - // Inferred labels now include full first relevant field, which in this case - // the address #1. - EXPECT_EQ(ASCIIToUTF16("3734 Elvis Presley Blvd."), labels[0]); - EXPECT_EQ(ASCIIToUTF16("123 Apple St."), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("Elvis"), + ASCIIToUTF16("Charles") + }; + string16 expected_labels[] = { + ASCIIToUTF16("3734 Elvis Presley Blvd."), + ASCIIToUTF16("123 Apple St.") + }; + string16 expected_icons[] = {string16(), string16()}; + int expected_unique_ids[] = {1, 2}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); process()->sink().ClearMessages(); autofill_test::CreateTestFormField( "Card Number", "cardnumber", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + const int kPageID2 = 2; + rvh()->ResetAutoFillState(kPageID2); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. rvh()->AutocompleteSuggestionsReturned(std::vector<string16>()); // Test that we sent the right message to the renderer. - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(1U, values.size()); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION), - values[0]); - ASSERT_EQ(1U, labels.size()); - EXPECT_EQ(string16(), labels[0]); - ASSERT_EQ(1U, icons.size()); - EXPECT_EQ(string16(), icons[0]); + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values2[] = { + l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION) + }; + string16 expected_labels2[] = {string16()}; + string16 expected_icons2[] = {string16()}; + int expected_unique_ids2[] = {-1}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kPageID2, arraysize(expected_values2), expected_values2, + expected_labels2, expected_icons2, expected_unique_ids2); // Clear the test credit cards and try again -- we shouldn't return a warning. test_personal_data_->ClearCreditCards(); - EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(false, field)); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field)); } // Test that we correctly combine autofill and autocomplete suggestions. TEST_F(AutoFillManagerTest, GetCombinedAutoFillAndAutocompleteSuggestions) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(false, field)); + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // Add some Autocomplete suggestions. // This triggers the combined message send. std::vector<string16> suggestions; suggestions.push_back(ASCIIToUTF16("Jay")); + // This suggestion is a duplicate, and should be trimmed. + suggestions.push_back(ASCIIToUTF16("Elvis")); suggestions.push_back(ASCIIToUTF16("Jason")); rvh()->AutocompleteSuggestionsReturned(suggestions); @@ -899,46 +1097,43 @@ TEST_F(AutoFillManagerTest, GetCombinedAutoFillAndAutocompleteSuggestions) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(4U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]); - EXPECT_EQ(ASCIIToUTF16("Charles"), values[1]); - EXPECT_EQ(ASCIIToUTF16("Jay"), values[2]); - EXPECT_EQ(ASCIIToUTF16("Jason"), values[3]); - ASSERT_EQ(4U, labels.size()); - EXPECT_EQ(ASCIIToUTF16("3734 Elvis Presley Blvd."), labels[0]); - EXPECT_EQ(ASCIIToUTF16("123 Apple St."), labels[1]); - EXPECT_EQ(string16(), labels[2]); - EXPECT_EQ(string16(), labels[3]); - ASSERT_EQ(4U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); - EXPECT_EQ(string16(), icons[2]); - EXPECT_EQ(string16(), icons[3]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("Elvis"), + ASCIIToUTF16("Charles"), + ASCIIToUTF16("Jay"), + ASCIIToUTF16("Jason") + }; + string16 expected_labels[] = { + ASCIIToUTF16("3734 Elvis Presley Blvd."), + ASCIIToUTF16("123 Apple St."), + string16(), + string16() + }; + string16 expected_icons[] = {string16(), string16(), string16(), string16()}; + int expected_unique_ids[] = {1, 2, 0, 0}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we return autocomplete-like suggestions when trying to autofill -// already filled fields. -TEST_F(AutoFillManagerTest, GetFieldSuggestionsFieldIsAutoFilled) { +// already filled forms. +TEST_F(AutoFillManagerTest, GetFieldSuggestionsWhenFormIsAutoFilled) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(true, field)); + // Mark one of the fields as filled. + form.fields[2].set_autofilled(true); + const FormField& field = form.fields[0]; + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -949,40 +1144,36 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsFieldIsAutoFilled) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]); - EXPECT_EQ(ASCIIToUTF16("Charles"), values[1]); - ASSERT_EQ(2U, labels.size()); - EXPECT_EQ(string16(), labels[0]); - EXPECT_EQ(string16(), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + string16 expected_values[] = { + ASCIIToUTF16("Elvis"), + ASCIIToUTF16("Charles") + }; + string16 expected_labels[] = {string16(), string16()}; + string16 expected_icons[] = {string16(), string16()}; + int expected_unique_ids[] = {1, 2}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that nothing breaks when there are autocomplete suggestions but no // autofill suggestions. TEST_F(AutoFillManagerTest, GetFieldSuggestionsForAutocompleteOnly) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); - autofill_manager_->FormsSeen(forms); - - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; + FormField field; autofill_test::CreateTestFormField( "Some Field", "somefield", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(true, field)); + form.fields.push_back(field); + std::vector<FormData> forms(1, form); + autofill_manager_->FormsSeen(forms); + + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_FALSE(autofill_manager_->GetAutoFillSuggestions(form, field)); // Add some Autocomplete suggestions. // This triggers the combined message send. @@ -996,46 +1187,42 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsForAutocompleteOnly) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - ASSERT_EQ(2U, labels.size()); - EXPECT_EQ(ASCIIToUTF16("one"), values[0]); - EXPECT_EQ(string16(), labels[0]); - EXPECT_EQ(ASCIIToUTF16("two"), values[1]); - EXPECT_EQ(string16(), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("one"), + ASCIIToUTF16("two") + }; + string16 expected_labels[] = {string16(), string16()}; + string16 expected_icons[] = {string16(), string16()}; + int expected_unique_ids[] = {0, 0}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we do not return duplicate values drawn from multiple profiles when // filling an already filled field. TEST_F(AutoFillManagerTest, GetFieldSuggestionsWithDuplicateValues) { + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); // |profile| will be owned by the mock PersonalDataManager. AutoFillProfile* profile = new AutoFillProfile; autofill_test::SetProfileInfo(profile, "Duplicate", "Elvis", "", "", "", "", "", "", "", "", "", "", "", ""); + profile->set_guid("00000000-0000-0000-0000-000000000101"); autofill_manager_->AddProfile(profile); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - rvh()->ResetAutoFillState(kPageID); - EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(true, field)); + FormField& field = form.fields[0]; + field.set_autofilled(true); + rvh()->ResetAutoFillState(kDefaultPageID); + EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(form, field)); // No suggestions provided, so send an empty vector as the results. // This triggers the combined message send. @@ -1046,322 +1233,202 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsWithDuplicateValues) { std::vector<string16> values; std::vector<string16> labels; std::vector<string16> icons; - EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, - &icons)); - EXPECT_EQ(kPageID, page_id); - ASSERT_EQ(2U, values.size()); - EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]); - EXPECT_EQ(ASCIIToUTF16("Charles"), values[1]); - ASSERT_EQ(2U, labels.size()); - EXPECT_EQ(string16(), labels[0]); - EXPECT_EQ(string16(), labels[1]); - ASSERT_EQ(2U, icons.size()); - EXPECT_EQ(string16(), icons[0]); - EXPECT_EQ(string16(), icons[1]); + std::vector<int> unique_ids; + EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels, &icons, + &unique_ids)); + + string16 expected_values[] = { + ASCIIToUTF16("Elvis"), + ASCIIToUTF16("Charles") + }; + string16 expected_labels[] = {string16(), string16()}; + string16 expected_icons[] = {string16(), string16()}; + int expected_unique_ids[] = {1, 2}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); } // Test that we correctly fill an address form. TEST_F(AutoFillManagerTest, FillAddressForm) { - // |profile| will be owned by the mock PersonalDataManager. - AutoFillProfile* profile = new AutoFillProfile; - autofill_test::SetProfileInfo(profile, "Home; 8765", "Joe", "", "Ely", - "flatlander@gmail.com", "MCA", - "916 16th St.", "Apt. 6", "Lubbock", - "Texas", "79401", "USA", - "12345678901", ""); - autofill_manager_->AddProfile(profile); - + // Set up our form data. FormData form; CreateTestAddressFormData(&form); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; + std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid(); EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( - kPageID, form, autofill_manager_->PackGUIDs(std::string(), - profile->guid()))); + kDefaultPageID, form, form.fields[0], + autofill_manager_->PackGUIDs(std::string(), guid))); int page_id = 0; FormData results; EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); - EXPECT_EQ(ASCIIToUTF16("MyForm"), results.name); - EXPECT_EQ(ASCIIToUTF16("POST"), results.method); - EXPECT_EQ(GURL("http://myform.com/form.html"), results.origin); - EXPECT_EQ(GURL("http://myform.com/submit.html"), results.action); - ASSERT_EQ(11U, results.fields.size()); - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "Joe", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[0])); - autofill_test::CreateTestFormField( - "Middle Name", "middlename", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[1])); - autofill_test::CreateTestFormField( - "Last Name", "lastname", "Ely", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[2])); - autofill_test::CreateTestFormField( - "Address Line 1", "addr1", "916 16th St.", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[3])); - autofill_test::CreateTestFormField( - "Address Line 2", "addr2", "Apt. 6", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[4])); - autofill_test::CreateTestFormField( - "City", "city", "Lubbock", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[5])); - autofill_test::CreateTestFormField( - "State", "state", "Texas", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[6])); - autofill_test::CreateTestFormField( - "Postal Code", "zipcode", "79401", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[7])); - autofill_test::CreateTestFormField( - "Country", "country", "USA", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[8])); - autofill_test::CreateTestFormField( - "Phone Number", "phonenumber", "12345678901", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[9])); - autofill_test::CreateTestFormField( - "Email", "email", "flatlander@gmail.com", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[10])); + ExpectFilledAddressFormElvis(page_id, results, kDefaultPageID, false); } // Test that we correctly fill a credit card form. TEST_F(AutoFillManagerTest, FillCreditCardForm) { + // Set up our form data. FormData form; CreateTestCreditCardFormData(&form, true); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; + std::string guid = autofill_manager_->GetLabeledCreditCard("First")->guid(); EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( - kPageID, form, - autofill_manager_->PackGUIDs("00000000-0000-0000-0000-000000000004", - std::string()))); + kDefaultPageID, form, *form.fields.begin(), + autofill_manager_->PackGUIDs(guid, std::string()))); int page_id = 0; FormData results; EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); - EXPECT_EQ(ASCIIToUTF16("MyForm"), results.name); - EXPECT_EQ(ASCIIToUTF16("POST"), results.method); - EXPECT_EQ(GURL("https://myform.com/form.html"), results.origin); - EXPECT_EQ(GURL("https://myform.com/submit.html"), results.action); - ASSERT_EQ(4U, results.fields.size()); - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "Name on Card", "nameoncard", "Elvis Presley", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[0])); - autofill_test::CreateTestFormField( - "Card Number", "cardnumber", "4234567890123456", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[1])); - autofill_test::CreateTestFormField( - "Expiration Date", "ccmonth", "04", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[2])); - autofill_test::CreateTestFormField( - "", "ccyear", "2012", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[3])); + ExpectFilledCreditCardFormElvis(page_id, results, kDefaultPageID, false); } // Test that we correctly fill a combined address and credit card form. TEST_F(AutoFillManagerTest, FillAddressAndCreditCardForm) { - // |profile| will be owned by the mock PersonalDataManager. - AutoFillProfile* profile = new AutoFillProfile; - autofill_test::SetProfileInfo(profile, "Home; 8765", "Joe", "", "Ely", - "flatlander@gmail.com", "MCA", - "916 16th St.", "Apt. 6", "Lubbock", - "Texas", "79401", "USA", - "12345678901", ""); - profile->set_guid("00000000-0000-0000-0000-000000000008"); - autofill_manager_->AddProfile(profile); - + // Set up our form data. FormData form; CreateTestAddressFormData(&form); CreateTestCreditCardFormData(&form, true); - - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); // First fill the address data. - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; + std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid(); EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( - kPageID, form, - autofill_manager_->PackGUIDs(std::string(), - "00000000-0000-0000-0000-000000000008"))); + kDefaultPageID, form, form.fields[0], + autofill_manager_->PackGUIDs(std::string(), guid))); int page_id = 0; FormData results; EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); - EXPECT_EQ(ASCIIToUTF16("MyForm"), results.name); - EXPECT_EQ(ASCIIToUTF16("POST"), results.method); - EXPECT_EQ(GURL("https://myform.com/form.html"), results.origin); - EXPECT_EQ(GURL("https://myform.com/submit.html"), results.action); - ASSERT_EQ(15U, results.fields.size()); - - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "Joe", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[0])); - autofill_test::CreateTestFormField( - "Middle Name", "middlename", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[1])); - autofill_test::CreateTestFormField( - "Last Name", "lastname", "Ely", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[2])); - autofill_test::CreateTestFormField( - "Address Line 1", "addr1", "916 16th St.", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[3])); - autofill_test::CreateTestFormField( - "Address Line 2", "addr2", "Apt. 6", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[4])); - autofill_test::CreateTestFormField( - "City", "city", "Lubbock", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[5])); - autofill_test::CreateTestFormField( - "State", "state", "Texas", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[6])); - autofill_test::CreateTestFormField( - "Postal Code", "zipcode", "79401", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[7])); - autofill_test::CreateTestFormField( - "Country", "country", "USA", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[8])); - autofill_test::CreateTestFormField( - "Phone Number", "phonenumber", "12345678901", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[9])); - autofill_test::CreateTestFormField( - "Email", "email", "flatlander@gmail.com", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[10])); - autofill_test::CreateTestFormField( - "Name on Card", "nameoncard", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[11])); - autofill_test::CreateTestFormField( - "Card Number", "cardnumber", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[12])); - autofill_test::CreateTestFormField( - "Expiration Date", "ccmonth", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[13])); - autofill_test::CreateTestFormField( - "", "ccyear", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[14])); + { + SCOPED_TRACE("Address"); + ExpectFilledAddressFormElvis(page_id, results, kDefaultPageID, true); + } // Now fill the credit card data. process()->sink().ClearMessages(); + const int kPageID2 = 2; + guid = autofill_manager_->GetLabeledCreditCard("First")->guid(); + EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( + kPageID2, form, form.fields.back(), + autofill_manager_->PackGUIDs(guid, std::string()))); + + page_id = 0; + EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); + { + SCOPED_TRACE("Credit card"); + ExpectFilledCreditCardFormElvis(page_id, results, kPageID2, true); + } +} + +// Test that we correctly fill a previously auto-filled form. +TEST_F(AutoFillManagerTest, FillAutoFilledForm) { + // Set up our form data. + FormData form; + CreateTestAddressFormData(&form); + // Mark one of the address fields as autofilled. + form.fields[4].set_autofilled(true); + CreateTestCreditCardFormData(&form, true); + std::vector<FormData> forms(1, form); + autofill_manager_->FormsSeen(forms); + + // First fill the address data. + std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid(); EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( - kPageID, form, - autofill_manager_->PackGUIDs("00000000-0000-0000-0000-000000000004", - std::string()))); + kDefaultPageID, form, *form.fields.begin(), + autofill_manager_->PackGUIDs(std::string(), guid))); + int page_id = 0; + FormData results; + EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); + { + SCOPED_TRACE("Address"); + ExpectFilledForm(page_id, results, kDefaultPageID, + "Elvis", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", true, true); + } + + // Now fill the credit card data. + process()->sink().ClearMessages(); + const int kPageID2 = 2; + guid = autofill_manager_->GetLabeledCreditCard("First")->guid(); + EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( + kPageID2, form, form.fields.back(), + autofill_manager_->PackGUIDs(guid, std::string()))); page_id = 0; EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); - EXPECT_EQ(ASCIIToUTF16("MyForm"), results.name); - EXPECT_EQ(ASCIIToUTF16("POST"), results.method); - EXPECT_EQ(GURL("https://myform.com/form.html"), results.origin); - EXPECT_EQ(GURL("https://myform.com/submit.html"), results.action); - ASSERT_EQ(15U, results.fields.size()); + { + SCOPED_TRACE("Credit card 1"); + ExpectFilledCreditCardFormElvis(page_id, results, kPageID2, true); + } - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[0])); - autofill_test::CreateTestFormField( - "Middle Name", "middlename", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[1])); - autofill_test::CreateTestFormField( - "Last Name", "lastname", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[2])); - autofill_test::CreateTestFormField( - "Address Line 1", "addr1", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[3])); - autofill_test::CreateTestFormField( - "Address Line 2", "addr2", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[4])); - autofill_test::CreateTestFormField( - "City", "city", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[5])); - autofill_test::CreateTestFormField( - "State", "state", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[6])); - autofill_test::CreateTestFormField( - "Postal Code", "zipcode", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[7])); - autofill_test::CreateTestFormField( - "Country", "country", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[8])); - autofill_test::CreateTestFormField( - "Phone Number", "phonenumber", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[9])); - autofill_test::CreateTestFormField( - "Email", "email", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[10])); - autofill_test::CreateTestFormField( - "Name on Card", "nameoncard", "Elvis Presley", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[11])); - autofill_test::CreateTestFormField( - "Card Number", "cardnumber", "4234567890123456", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[12])); - autofill_test::CreateTestFormField( - "Expiration Date", "ccmonth", "04", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[13])); - autofill_test::CreateTestFormField( - "", "ccyear", "2012", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[14])); + // Now set the credit card fields to also be auto-filled, and try again to + // fill the credit card data + for (std::vector<FormField>::iterator iter = form.fields.begin(); + iter != form.fields.end(); + ++iter){ + iter->set_autofilled(true); + } + + process()->sink().ClearMessages(); + const int kPageID3 = 3; + EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( + kPageID3, form, *form.fields.rbegin(), + autofill_manager_->PackGUIDs(guid, std::string()))); + + page_id = 0; + EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); + { + SCOPED_TRACE("Credit card 2"); + ExpectFilledForm(page_id, results, kPageID3, + "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "2012", true, true); + } } // Test that we correctly fill a phone number split across multiple fields. TEST_F(AutoFillManagerTest, FillPhoneNumber) { + // Set up our form data. FormData form; - form.name = ASCIIToUTF16("MyPhoneForm"); form.method = ASCIIToUTF16("POST"); form.origin = GURL("http://myform.com/phone_form.html"); form.action = GURL("http://myform.com/phone_submit.html"); form.user_submitted = true; - webkit_glue::FormField field; - + FormField field; autofill_test::CreateTestFormField( "country code", "country code", "", "text", &field); - field.set_size(1); + field.set_max_length(1); form.fields.push_back(field); autofill_test::CreateTestFormField( "area code", "area code", "", "text", &field); - field.set_size(3); + field.set_max_length(3); form.fields.push_back(field); autofill_test::CreateTestFormField( "phone", "phone prefix", "1", "text", &field); - field.set_size(3); + field.set_max_length(3); form.fields.push_back(field); autofill_test::CreateTestFormField( "-", "phone suffix", "", "text", &field); - field.set_size(4); + field.set_max_length(4); form.fields.push_back(field); autofill_test::CreateTestFormField( "Phone Extension", "ext", "", "text", &field); - field.set_size(3); + field.set_max_length(3); form.fields.push_back(field); - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); AutoFillProfile *work_profile = autofill_manager_->GetLabeledProfile("Work"); - EXPECT_TRUE(work_profile != NULL); + ASSERT_TRUE(work_profile != NULL); const AutoFillType phone_type(PHONE_HOME_NUMBER); string16 saved_phone = work_profile->GetFieldText(phone_type); @@ -1374,7 +1441,7 @@ TEST_F(AutoFillManagerTest, FillPhoneNumber) { int page_id = 100 - i; process()->sink().ClearMessages(); EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( - page_id, form, + page_id, form, *form.fields.begin(), autofill_manager_->PackGUIDs(std::string(), work_profile->guid()))); page_id = 0; FormData results; @@ -1395,139 +1462,61 @@ TEST_F(AutoFillManagerTest, FillPhoneNumber) { // Test that we can still fill a form when a field has been removed from it. TEST_F(AutoFillManagerTest, FormChangesRemoveField) { + // Set up our form data. FormData form; - form.name = ASCIIToUTF16("MyForm"); - form.method = ASCIIToUTF16("POST"); - form.origin = GURL("http://myform.com/form.html"); - form.action = GURL("http://myform.com/submit.html"); - form.user_submitted = true; + CreateTestAddressFormData(&form); - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Middle Name", "middlename", "", "text", &field); - form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Last Name", "lastname", "", "text", &field); - form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Phone Number", "phonenumber", "", "text", &field); - form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Email", "email", "", "text", &field); - form.fields.push_back(field); + // Add a field -- we'll remove it again later. + FormField field; + autofill_test::CreateTestFormField("Some", "field", "", "text", &field); + form.fields.insert(form.fields.begin() + 3, field); - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // Now, after the call to |FormsSeen| we remove the phone number field before - // filling. + // Now, after the call to |FormsSeen|, we remove the field before filling. form.fields.erase(form.fields.begin() + 3); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; + std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid(); EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( - kPageID, form, - autofill_manager_->PackGUIDs(std::string(), - "00000000-0000-0000-0000-000000000001"))); + kDefaultPageID, form, form.fields[0], + autofill_manager_->PackGUIDs(std::string(), guid))); int page_id = 0; FormData results; EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); - EXPECT_EQ(ASCIIToUTF16("MyForm"), results.name); - EXPECT_EQ(ASCIIToUTF16("POST"), results.method); - EXPECT_EQ(GURL("http://myform.com/form.html"), results.origin); - EXPECT_EQ(GURL("http://myform.com/submit.html"), results.action); - EXPECT_TRUE(results.user_submitted); - ASSERT_EQ(4U, results.fields.size()); - - autofill_test::CreateTestFormField( - "First Name", "firstname", "Elvis", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[0])); - autofill_test::CreateTestFormField( - "Middle Name", "middlename", "Aaron", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[1])); - autofill_test::CreateTestFormField( - "Last Name", "lastname", "Presley", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[2])); - autofill_test::CreateTestFormField( - "Email", "email", "theking@gmail.com", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[3])); + ExpectFilledAddressFormElvis(page_id, results, kDefaultPageID, false); } // Test that we can still fill a form when a field has been added to it. TEST_F(AutoFillManagerTest, FormChangesAddField) { + // The offset of the fax field in the address form. + const int kFaxFieldOffset = 10; + + // Set up our form data. FormData form; - form.name = ASCIIToUTF16("MyForm"); - form.method = ASCIIToUTF16("POST"); - form.origin = GURL("http://myform.com/form.html"); - form.action = GURL("http://myform.com/submit.html"); - form.user_submitted = true; + CreateTestAddressFormData(&form); - webkit_glue::FormField field; - autofill_test::CreateTestFormField( - "First Name", "firstname", "", "text", &field); - form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Middle Name", "middlename", "", "text", &field); - form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Last Name", "lastname", "", "text", &field); - // Note: absent phone number. Adding this below. - form.fields.push_back(field); - autofill_test::CreateTestFormField( - "Email", "email", "", "text", &field); - form.fields.push_back(field); + // Remove the fax field -- we'll add it back later. + std::vector<FormField>::iterator pos = form.fields.begin() + kFaxFieldOffset; + FormField field = *pos; + pos = form.fields.erase(pos); - // Set up our FormStructures. - std::vector<FormData> forms; - forms.push_back(form); + std::vector<FormData> forms(1, form); autofill_manager_->FormsSeen(forms); - // Now, after the call to |FormsSeen| we add the phone number field before - // filling. - autofill_test::CreateTestFormField( - "Phone Number", "phonenumber", "", "text", &field); - form.fields.insert(form.fields.begin() + 3, field); + // Now, after the call to |FormsSeen|, we restore the field before filling. + form.fields.insert(pos, field); - // The page ID sent to the AutoFillManager from the RenderView, used to send - // an IPC message back to the renderer. - const int kPageID = 1; + std::string guid = autofill_manager_->GetLabeledProfile("Home")->guid(); EXPECT_TRUE(autofill_manager_->FillAutoFillFormData( - kPageID, form, - autofill_manager_->PackGUIDs(std::string(), - "00000000-0000-0000-0000-000000000001"))); + kDefaultPageID, form, form.fields[0], + autofill_manager_->PackGUIDs(std::string(), guid))); int page_id = 0; FormData results; EXPECT_TRUE(GetAutoFillFormDataFilledMessage(&page_id, &results)); - EXPECT_EQ(ASCIIToUTF16("MyForm"), results.name); - EXPECT_EQ(ASCIIToUTF16("POST"), results.method); - EXPECT_EQ(GURL("http://myform.com/form.html"), results.origin); - EXPECT_EQ(GURL("http://myform.com/submit.html"), results.action); - EXPECT_TRUE(results.user_submitted); - ASSERT_EQ(5U, results.fields.size()); - - autofill_test::CreateTestFormField( - "First Name", "firstname", "Elvis", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[0])); - autofill_test::CreateTestFormField( - "Middle Name", "middlename", "Aaron", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[1])); - autofill_test::CreateTestFormField( - "Last Name", "lastname", "Presley", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[2])); - autofill_test::CreateTestFormField( - "Phone Number", "phonenumber", "", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[3])); - autofill_test::CreateTestFormField( - "Email", "email", "theking@gmail.com", "text", &field); - EXPECT_TRUE(field.StrictlyEqualsHack(results.fields[4])); + ExpectFilledAddressFormElvis(page_id, results, kDefaultPageID, false); } TEST_F(AutoFillManagerTest, HiddenFields) { @@ -1538,7 +1527,7 @@ TEST_F(AutoFillManagerTest, HiddenFields) { form.action = GURL("http://myform.com/submit.html"); form.user_submitted = true; - webkit_glue::FormField field; + FormField field; autofill_test::CreateTestFormField( "E-mail", "one", "one", "hidden", &field); form.fields.push_back(field); @@ -1549,7 +1538,7 @@ TEST_F(AutoFillManagerTest, HiddenFields) { "E-mail", "three", "three", "hidden", &field); form.fields.push_back(field); - // Set up our FormStructures. + // Set up our form data. std::vector<FormData> forms; forms.push_back(form); autofill_manager_->FormsSeen(forms); diff --git a/chrome/browser/autofill/autofill_metrics.cc b/chrome/browser/autofill/autofill_metrics.cc new file mode 100644 index 0000000..85b5517 --- /dev/null +++ b/chrome/browser/autofill/autofill_metrics.cc @@ -0,0 +1,18 @@ +// 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 "chrome/browser/autofill/autofill_metrics.h" + +#include "base/metrics/histogram.h" + +namespace autofill_metrics { + +void LogServerQueryMetric(ServerQueryMetricType type) { + DCHECK(type < NUM_SERVER_QUERY_METRICS); + + UMA_HISTOGRAM_ENUMERATION("AutoFill.ServerQueryResponse", type, + NUM_SERVER_QUERY_METRICS); +} + +} // namespace autofill_metrics diff --git a/chrome/browser/autofill/autofill_metrics.h b/chrome/browser/autofill/autofill_metrics.h new file mode 100644 index 0000000..d461668 --- /dev/null +++ b/chrome/browser/autofill/autofill_metrics.h @@ -0,0 +1,37 @@ +// 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. + +#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_METRICS_H_ +#define CHROME_BROWSER_AUTOFILL_AUTOFILL_METRICS_H_ +#pragma once + +namespace autofill_metrics { + +// Each of these should be logged at most once per query to the server, which in +// turn should occur at most once per page load. +enum ServerQueryMetricType { + // Logged for each query sent to the server + QUERY_SENT = 0, + // Logged for each query response received from the server + QUERY_RESPONSE_RECEIVED, + // Logged for each parsable response received from the server + QUERY_RESPONSE_PARSED, + // Logged for each parsable response that provided no improvements relative to + // our heuristics. + QUERY_RESPONSE_MATCHED_LOCAL_HEURISTICS, + // Logged for each page for which our heuristics detected at least one + // auto-fillable field, but the server response overrode the type of at least + // one field + QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS, + // Logged for each page for which our heuristics did not detect any + // auto-fillable fields, but the server response did detect some. + QUERY_RESPONSE_WITH_NO_LOCAL_HEURISTICS, + NUM_SERVER_QUERY_METRICS +}; + +void LogServerQueryMetric(ServerQueryMetricType type); + +} // namespace autofill_metrics + +#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_METRICS_H_ diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc index 9f760b8..263df46 100644 --- a/chrome/browser/autofill/autofill_profile.cc +++ b/chrome/browser/autofill/autofill_profile.cc @@ -436,7 +436,9 @@ bool AutoFillProfile::operator!=(const AutoFillProfile& profile) const { const string16 AutoFillProfile::PrimaryValue() const { return GetFieldText(AutoFillType(NAME_FULL)) + - GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)); + GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)) + + GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)) + + GetFieldText(AutoFillType(EMAIL_ADDRESS)); } Address* AutoFillProfile::GetHomeAddress() { diff --git a/chrome/browser/autofill/credit_card_field.cc b/chrome/browser/autofill/credit_card_field.cc index 6b85077..f8b4c5e 100644 --- a/chrome/browser/autofill/credit_card_field.cc +++ b/chrome/browser/autofill/credit_card_field.cc @@ -88,6 +88,22 @@ CreditCardField* CreditCardField::Parse( } } + // We look for a card security code before we look for a credit + // card number and match the general term "number". The security code + // has a plethora of names; we've seen "verification #", + // "verification number", "card identification number" and others listed + // in the |pattern| below. + if (is_ecml) { + pattern = GetEcmlPattern(kEcmlCardVerification); + } else { + pattern = ASCIIToUTF16("verification|card identification|cvn|" + "security code|cvv code|cvc"); + } + + if (credit_card_field->verification_ == NULL && + ParseText(&q, pattern, &credit_card_field->verification_)) + continue; + // TODO(jhawkins): Parse the type select control. if (is_ecml) @@ -155,7 +171,11 @@ CreditCardField* CreditCardField::Parse( // 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_ && + // The existence of a number or cvc in combination with expiration date is + // a strong enough signal that this is a credit card. It is possible that + // the number and name were parsed in a separate part of the form. So if + // the cvc and date were found independently they are returned. + if ((credit_card_field->number_ || credit_card_field->verification_) && credit_card_field->expiration_month_ && credit_card_field->expiration_year_) { *iter = q; @@ -170,6 +190,7 @@ CreditCardField::CreditCardField() cardholder_last_(NULL), type_(NULL), number_(NULL), + verification_(NULL), expiration_month_(NULL), expiration_year_(NULL) { } diff --git a/chrome/browser/autofill/credit_card_field.h b/chrome/browser/autofill/credit_card_field.h index e3b443d..fdb52bd 100644 --- a/chrome/browser/autofill/credit_card_field.h +++ b/chrome/browser/autofill/credit_card_field.h @@ -39,6 +39,9 @@ class CreditCardField : public FormField { AutoFillField* type_; // Optional. TODO(jhawkins): Parse the select control. AutoFillField* number_; // Required. + // The 3-digit card verification number; we don't currently fill this. + AutoFillField* verification_; + // 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 index c333032..8c41b4f 100644 --- a/chrome/browser/autofill/credit_card_field_unittest.cc +++ b/chrome/browser/autofill/credit_card_field_unittest.cc @@ -46,14 +46,16 @@ TEST_F(CreditCardFieldTest, ParseCreditCardNoNumber) { ASCIIToUTF16("ccmonth"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("month1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"), ASCIIToUTF16("ccyear"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("year1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -67,7 +69,8 @@ TEST_F(CreditCardFieldTest, ParseCreditCardNoDate) { ASCIIToUTF16("card_number"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("number1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -81,21 +84,24 @@ TEST_F(CreditCardFieldTest, ParseMiniumCreditCard) { ASCIIToUTF16("card_number"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("number1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Month"), ASCIIToUTF16("ccmonth"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("month1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"), ASCIIToUTF16("ccyear"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("year1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -120,7 +126,8 @@ TEST_F(CreditCardFieldTest, ParseMiniumCreditCardEcml) { ASCIIToUTF16(kEcmlCardNumber), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("number1"))); list_.push_back( new AutoFillField( @@ -128,7 +135,8 @@ TEST_F(CreditCardFieldTest, ParseMiniumCreditCardEcml) { ASCIIToUTF16(kEcmlCardExpireMonth), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("month1"))); list_.push_back( new AutoFillField( @@ -136,7 +144,8 @@ TEST_F(CreditCardFieldTest, ParseMiniumCreditCardEcml) { ASCIIToUTF16(kEcmlCardExpireYear), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("year1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -161,35 +170,40 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCard) { ASCIIToUTF16("name on card"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16("card_number"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("number1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Month"), ASCIIToUTF16("ccmonth"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("month1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Exp Year"), ASCIIToUTF16("ccyear"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("year1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Verification"), ASCIIToUTF16("verification"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("cvc1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -220,14 +234,16 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCardEcml) { ASCIIToUTF16(kEcmlCardHolder), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16(kEcmlCardNumber), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("number1"))); list_.push_back( new AutoFillField( @@ -235,7 +251,8 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCardEcml) { ASCIIToUTF16(kEcmlCardExpireMonth), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("month1"))); list_.push_back( new AutoFillField( @@ -243,7 +260,8 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCardEcml) { ASCIIToUTF16(kEcmlCardExpireYear), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("year1"))); list_.push_back( new AutoFillField( @@ -251,7 +269,8 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCardEcml) { ASCIIToUTF16(kEcmlCardVerification), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("cvc1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -282,14 +301,16 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear) { ASCIIToUTF16("Name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16("Card"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("number"))); list_.push_back( new AutoFillField( @@ -297,7 +318,8 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear) { ASCIIToUTF16("ExpDate"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("month"))); list_.push_back( new AutoFillField( @@ -305,7 +327,8 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear) { ASCIIToUTF16("ExpDate"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("year"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -333,14 +356,16 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear2) { ASCIIToUTF16("Name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16("Card"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("number"))); list_.push_back( new AutoFillField( @@ -348,7 +373,8 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear2) { ASCIIToUTF16("ExpDate"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("month"))); list_.push_back( new AutoFillField( @@ -356,7 +382,8 @@ TEST_F(CreditCardFieldTest, ParseExpMonthYear2) { ASCIIToUTF16("ExpDate"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("year"))); list_.push_back(NULL); iter_ = list_.begin(); diff --git a/chrome/browser/autofill/fax_field_unittest.cc b/chrome/browser/autofill/fax_field_unittest.cc index 0ba21c0..724456a 100644 --- a/chrome/browser/autofill/fax_field_unittest.cc +++ b/chrome/browser/autofill/fax_field_unittest.cc @@ -46,7 +46,8 @@ TEST_F(FaxFieldTest, ParseOneLineFax) { ASCIIToUTF16("faxnumber"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("fax1"))); list_.push_back(NULL); iter_ = list_.begin(); diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc index 509ee33..f8a103f 100644 --- a/chrome/browser/autofill/form_structure.cc +++ b/chrome/browser/autofill/form_structure.cc @@ -9,6 +9,7 @@ #include "base/sha1.h" #include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" +#include "chrome/browser/autofill/autofill_metrics.h" #include "chrome/browser/autofill/autofill_xml_parser.h" #include "chrome/browser/autofill/field_types.h" #include "chrome/browser/autofill/form_field.h" @@ -204,6 +205,9 @@ bool FormStructure::EncodeQueryRequest(const ScopedVector<FormStructure>& forms, void FormStructure::ParseQueryResponse(const std::string& response_xml, const std::vector<FormStructure*>& forms, UploadRequired* upload_required) { + autofill_metrics::LogServerQueryMetric( + autofill_metrics::QUERY_RESPONSE_RECEIVED); + // Parse the field types from the server response to the query. std::vector<AutoFillFieldType> field_types; AutoFillQueryXmlParser parse_handler(&field_types, upload_required); @@ -212,16 +216,26 @@ void FormStructure::ParseQueryResponse(const std::string& response_xml, if (!parse_handler.succeeded()) return; + autofill_metrics::LogServerQueryMetric( + autofill_metrics::QUERY_RESPONSE_PARSED); + + bool heuristics_detected_fillable_field = false; + bool query_response_overrode_heuristics = false; + // Copy the field types into the actual form. std::vector<AutoFillFieldType>::iterator current_type = field_types.begin(); for (std::vector<FormStructure*>::const_iterator iter = forms.begin(); iter != forms.end(); ++iter) { FormStructure* form = *iter; + + if (form->has_autofillable_field_) + heuristics_detected_fillable_field = true; + form->has_credit_card_field_ = false; form->has_autofillable_field_ = false; for (std::vector<AutoFillField*>::iterator field = form->fields_.begin(); - field != form->fields_.end(); ++field) { + field != form->fields_.end(); ++field, ++current_type) { // The field list is terminated by a NULL AutoFillField. if (!*field) break; @@ -231,17 +245,32 @@ void FormStructure::ParseQueryResponse(const std::string& response_xml, if (current_type == field_types.end()) break; + AutoFillFieldType heuristic_type = (*field)->type(); (*field)->set_server_type(*current_type); + if (heuristic_type != (*field)->type()) + query_response_overrode_heuristics = true; + AutoFillType autofill_type((*field)->type()); if (autofill_type.group() == AutoFillType::CREDIT_CARD) form->has_credit_card_field_ = true; if (autofill_type.field_type() != UNKNOWN_TYPE) form->has_autofillable_field_ = true; - ++current_type; } form->UpdateAutoFillCount(); } + + autofill_metrics::ServerQueryMetricType metric_type; + if (query_response_overrode_heuristics) { + if (heuristics_detected_fillable_field) { + metric_type = autofill_metrics::QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS; + } else { + metric_type = autofill_metrics::QUERY_RESPONSE_WITH_NO_LOCAL_HEURISTICS; + } + } else { + metric_type = autofill_metrics::QUERY_RESPONSE_MATCHED_LOCAL_HEURISTICS; + } + autofill_metrics::LogServerQueryMetric(metric_type); } std::string FormStructure::FormSignature() const { diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc new file mode 100644 index 0000000..dc64052 --- /dev/null +++ b/chrome/browser/autofill/form_structure_browsertest.cc @@ -0,0 +1,216 @@ +// 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 <vector> + +#include "chrome/browser/autofill/autofill_manager.h" +#include "chrome/browser/autofill/form_structure.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" +#include "googleurl/src/gurl.h" + +// Test class for verifying proper form structure as determined by AutoFill +// heuristics. After a test loads HTML content with a call to |NavigateToURL| +// the |AutoFillManager| associated with the tab contents is queried for the +// form structures that were loaded and parsed. +// These form structures are serialized to string form and compared with +// expected results. +class FormStructureBrowserTest : public InProcessBrowserTest { + public: + FormStructureBrowserTest() {} + virtual ~FormStructureBrowserTest() {} + + protected: + // Returns a vector of form structure objects associated with the given + // |autofill_manager|. + const std::vector<FormStructure*>& GetFormStructures( + const AutoFillManager& autofill_manager); + + // Serializes the given form structures in |forms| to string form. + const std::string FormStructuresToString( + const std::vector<FormStructure*>& forms); + + private: + // A helper utility for converting an |AutoFillFieldType| to string form. + const std::string AutoFillFieldTypeToString(AutoFillFieldType type); + + DISALLOW_COPY_AND_ASSIGN(FormStructureBrowserTest); +}; + +const std::vector<FormStructure*>& FormStructureBrowserTest::GetFormStructures( + const AutoFillManager& autofill_manager) { + return autofill_manager.form_structures_.get(); +} + +const std::string FormStructureBrowserTest::FormStructuresToString( + const std::vector<FormStructure*>& forms) { + std::string forms_string; + for (std::vector<FormStructure*>::const_iterator iter = forms.begin(); + iter != forms.end(); + ++iter) { + forms_string += (*iter)->source_url().spec(); + forms_string += "\n"; + + for (std::vector<AutoFillField*>::const_iterator field_iter = + (*iter)->begin(); + field_iter != (*iter)->end(); + ++field_iter) { + // The field list is NULL-terminated. Exit loop when at the end. + if (!*field_iter) + break; + forms_string += AutoFillFieldTypeToString((*field_iter)->type()); + forms_string += "\n"; + } + } + return forms_string; +} + +const std::string FormStructureBrowserTest::AutoFillFieldTypeToString( + AutoFillFieldType type) { + switch (type) { + case NO_SERVER_DATA: + return "NO_SERVER_DATA"; + case UNKNOWN_TYPE: + return "UNKNOWN_TYPE"; + case EMPTY_TYPE: + return "EMPTY_TYPE"; + case NAME_FIRST: + return "NAME_FIRST"; + case NAME_MIDDLE: + return "NAME_MIDDLE"; + case NAME_LAST: + return "NAME_LAST"; + case NAME_MIDDLE_INITIAL: + return "NAME_MIDDLE_INITIAL"; + case NAME_FULL: + return "NAME_FULL"; + case NAME_SUFFIX: + return "NAME_SUFFIX"; + case EMAIL_ADDRESS: + return "EMAIL_ADDRESS"; + case PHONE_HOME_NUMBER: + return "PHONE_HOME_NUMBER"; + case PHONE_HOME_CITY_CODE: + return "PHONE_HOME_CITY_CODE"; + case PHONE_HOME_COUNTRY_CODE: + return "PHONE_HOME_COUNTRY_CODE"; + case PHONE_HOME_CITY_AND_NUMBER: + return "PHONE_HOME_CITY_AND_NUMBER"; + case PHONE_HOME_WHOLE_NUMBER: + return "PHONE_HOME_WHOLE_NUMBER"; + case PHONE_FAX_NUMBER: + return "PHONE_FAX_NUMBER"; + case PHONE_FAX_CITY_CODE: + return "PHONE_FAX_CITY_CODE"; + case PHONE_FAX_COUNTRY_CODE: + return "PHONE_FAX_COUNTRY_CODE"; + case PHONE_FAX_CITY_AND_NUMBER: + return "PHONE_FAX_CITY_AND_NUMBER"; + case PHONE_FAX_WHOLE_NUMBER: + return "PHONE_FAX_WHOLE_NUMBER"; + case ADDRESS_HOME_LINE1: + return "ADDRESS_HOME_LINE1"; + case ADDRESS_HOME_LINE2: + return "ADDRESS_HOME_LINE2"; + case ADDRESS_HOME_APT_NUM: + return "ADDRESS_HOME_APT_NUM"; + case ADDRESS_HOME_CITY: + return "ADDRESS_HOME_CITY"; + case ADDRESS_HOME_STATE: + return "ADDRESS_HOME_STATE"; + case ADDRESS_HOME_ZIP: + return "ADDRESS_HOME_ZIP"; + case ADDRESS_HOME_COUNTRY: + return "ADDRESS_HOME_COUNTRY"; + case ADDRESS_BILLING_LINE1: + return "ADDRESS_BILLING_LINE1"; + case ADDRESS_BILLING_LINE2: + return "ADDRESS_BILLING_LINE2"; + case ADDRESS_BILLING_APT_NUM: + return "ADDRESS_BILLING_APT_NUM"; + case ADDRESS_BILLING_CITY: + return "ADDRESS_BILLING_CITY"; + case ADDRESS_BILLING_STATE: + return "ADDRESS_BILLING_STATE"; + case ADDRESS_BILLING_ZIP: + return "ADDRESS_BILLING_ZIP"; + case ADDRESS_BILLING_COUNTRY: + return "ADDRESS_BILLING_COUNTRY"; + case CREDIT_CARD_NAME: + return "CREDIT_CARD_NAME"; + case CREDIT_CARD_NUMBER: + return "CREDIT_CARD_NUMBER"; + case CREDIT_CARD_EXP_MONTH: + return "CREDIT_CARD_EXP_MONTH"; + case CREDIT_CARD_EXP_2_DIGIT_YEAR: + return "CREDIT_CARD_EXP_2_DIGIT_YEAR"; + case CREDIT_CARD_EXP_4_DIGIT_YEAR: + return "CREDIT_CARD_EXP_4_DIGIT_YEAR"; + case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: + return "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR"; + case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: + return "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR"; + case CREDIT_CARD_TYPE: + return "CREDIT_CARD_TYPE"; + case CREDIT_CARD_VERIFICATION_CODE: + return "CREDIT_CARD_VERIFICATION_CODE"; + case COMPANY_NAME: + return "COMPANY_NAME"; + default: + NOTREACHED() << "Invalid AutoFillFieldType value."; + } + + return std::string(); +} + +IN_PROC_BROWSER_TEST_F(FormStructureBrowserTest, BasicFormStructure) { + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); + ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL( + browser(), GURL("data:text/html;charset=utf-8," + "<form action=\"http://www.google.com/\" method=\"POST\">" + "<label for=\"firstname\">First name:</label>" + " <input type=\"text\" id=\"firstname\"/><br />" + "<label for=\"lastname\">Last name:</label>" + " <input type=\"text\" id=\"lastname\" /><br />" + "<label for=\"address1\">Address line 1:</label>" + " <input type=\"text\" id=\"address1\" /><br />" + "<label for=\"address2\">Address line 2:</label>" + " <input type=\"text\" id=\"address2\" /><br />" + "<label for=\"city\">City:</label>" + " <input type=\"text\" id=\"city\" /><br />" + "</form>"))); + + ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(), + VIEW_ID_TAB_CONTAINER)); + ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), + VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); + + AutoFillManager* autofill_manager = + browser()->GetSelectedTabContents()->GetAutoFillManager(); + ASSERT_NE(static_cast<AutoFillManager*>(NULL), autofill_manager); + std::vector<FormStructure*> forms = GetFormStructures(*autofill_manager); + std::string expected("data:text/html;charset=utf-8," + "<form action=\"http://www.google.com/\"" + " method=\"POST\">" + "<label for=\"firstname\">First name:</label>" + " <input type=\"text\" id=\"firstname\"/><br />" + "<label for=\"lastname\">Last name:</label>" + " <input type=\"text\" id=\"lastname\" /><br />" + "<label for=\"address1\">Address line 1:</label>" + " <input type=\"text\" id=\"address1\" /><br />" + "<label for=\"address2\">Address line 2:</label>" + " <input type=\"text\" id=\"address2\" /><br />" + "<label for=\"city\">City:</label>" + " <input type=\"text\" id=\"city\" /><br />" + "</form>\n" + "NAME_FIRST\n" + "NAME_LAST\n" + "ADDRESS_HOME_LINE1\n" + "ADDRESS_HOME_LINE2\n" + "ADDRESS_HOME_CITY\n"); + + EXPECT_EQ(expected, FormStructureBrowserTest::FormStructuresToString(forms)); +} diff --git a/chrome/browser/autofill/form_structure_unittest.cc b/chrome/browser/autofill/form_structure_unittest.cc index 8eb03fd..96d8fff 100644 --- a/chrome/browser/autofill/form_structure_unittest.cc +++ b/chrome/browser/autofill/form_structure_unittest.cc @@ -48,17 +48,20 @@ TEST(FormStructureTest, FieldCount) { ASCIIToUTF16("username"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("password"), ASCIIToUTF16("password"), string16(), ASCIIToUTF16("password"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); FormStructure form_structure(form); // All fields are counted. @@ -72,22 +75,26 @@ TEST(FormStructureTest, AutoFillCount) { ASCIIToUTF16("username"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("password"), ASCIIToUTF16("password"), string16(), ASCIIToUTF16("password"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("state"), ASCIIToUTF16("state"), string16(), ASCIIToUTF16("select-one"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); FormStructure form_structure(form); // Only text and select fields that are heuristically matched are counted. @@ -113,12 +120,14 @@ TEST(FormStructureTest, HasAutoFillableValues) { ASCIIToUTF16("Submit1"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit2"), ASCIIToUTF16("dummy value"), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_FALSE(form_structure->HasAutoFillableValues()); @@ -127,12 +136,14 @@ TEST(FormStructureTest, HasAutoFillableValues) { ASCIIToUTF16("email"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("state"), ASCIIToUTF16("state"), string16(), ASCIIToUTF16("select-one"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_FALSE(form_structure->HasAutoFillableValues()); @@ -141,12 +152,14 @@ TEST(FormStructureTest, HasAutoFillableValues) { ASCIIToUTF16("firstname"), ASCIIToUTF16("John"), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), ASCIIToUTF16("Dear"), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->HasAutoFillableValues()); @@ -157,12 +170,14 @@ TEST(FormStructureTest, HasAutoFillableValues) { ASCIIToUTF16("Field1"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Field2"), ASCIIToUTF16("dummy value"), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_FALSE(form_structure->HasAutoFillableValues()); @@ -172,7 +187,8 @@ TEST(FormStructureTest, HasAutoFillableValues) { ASCIIToUTF16("fullname"), ASCIIToUTF16("John Dear"), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->HasAutoFillableValues()); } @@ -187,17 +203,20 @@ TEST(FormStructureTest, IsAutoFillable) { ASCIIToUTF16("username"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("password"), ASCIIToUTF16("password"), string16(), ASCIIToUTF16("password"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_FALSE(form_structure->IsAutoFillable(true)); @@ -206,12 +225,14 @@ TEST(FormStructureTest, IsAutoFillable) { ASCIIToUTF16("firstname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_FALSE(form_structure->IsAutoFillable(true)); @@ -220,7 +241,8 @@ TEST(FormStructureTest, IsAutoFillable) { ASCIIToUTF16("email"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); @@ -252,47 +274,56 @@ TEST(FormStructureTest, HeuristicsContactInfo) { ASCIIToUTF16("firstname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"), ASCIIToUTF16("email"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"), ASCIIToUTF16("phone"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"), ASCIIToUTF16("fax"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("City"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Zip code"), ASCIIToUTF16("zipcode"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); @@ -330,87 +361,104 @@ TEST(FormStructureTest, HeuristicsHiddenFields) { ASCIIToUTF16("firstname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden1"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden2"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"), ASCIIToUTF16("email"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden3"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"), ASCIIToUTF16("phone"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden4"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"), ASCIIToUTF16("fax"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden5"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden6"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("City"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden7"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Zip code"), ASCIIToUTF16("zipcode"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("hidden8"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); @@ -449,61 +497,71 @@ TEST(FormStructureTest, HeuristicsSample8) { ASCIIToUTF16("bill.first"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Your Last Name:"), ASCIIToUTF16("bill.last"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Street Address Line 1:"), ASCIIToUTF16("bill.street1"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Street Address Line 2:"), ASCIIToUTF16("bill.street2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("City:"), ASCIIToUTF16("bill.city"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("State (U.S.):"), ASCIIToUTF16("bill.state"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Zip/Postal Code:"), ASCIIToUTF16("BillTo.PostalCode"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Country:"), ASCIIToUTF16("bill.country"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Phone Number:"), ASCIIToUTF16("BillTo.Phone"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(10U, form_structure->field_count()); @@ -543,45 +601,52 @@ TEST(FormStructureTest, HeuristicsSample6) { ASCIIToUTF16("email"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Full name"), ASCIIToUTF16("name"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Company"), ASCIIToUTF16("company"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address"), ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("City"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); // TODO(jhawkins): Add state select control. form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Zip Code"), ASCIIToUTF16("Home.PostalCode"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); // TODO(jhawkins): Phone number. form.fields.push_back( webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), ASCIIToUTF16("continue"), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(7U, form_structure->field_count()); @@ -615,47 +680,56 @@ TEST(FormStructureTest, HeuristicsLabelsOnly) { string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"), string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"), string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"), string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Zip code"), string16(), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(9U, form_structure->field_count()); @@ -691,32 +765,38 @@ TEST(FormStructureTest, HeuristicsCreditCardInfo) { ASCIIToUTF16("name on card"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16("card_number"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Exp Month"), ASCIIToUTF16("ccmonth"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Exp Year"), ASCIIToUTF16("ccyear"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Verification"), ASCIIToUTF16("verification"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(6U, form_structure->field_count()); @@ -746,39 +826,46 @@ TEST(FormStructureTest, HeuristicsCreditCardInfoWithUnknownCardField) { ASCIIToUTF16("name on card"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); // This is not a field we know how to process. But we should skip over it // and process the other fields in the card block. form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Card Type"), ASCIIToUTF16("card_type"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16("card_number"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Exp Month"), ASCIIToUTF16("ccmonth"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Exp Year"), ASCIIToUTF16("ccyear"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Verification"), ASCIIToUTF16("verification"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(7U, form_structure->field_count()); @@ -811,25 +898,29 @@ TEST(FormStructureTest, ThreeAddressLines) { ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address Line2"), ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address Line3"), ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("City"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); @@ -857,25 +948,29 @@ TEST(FormStructureTest, BillingAndShippingAddresses) { ASCIIToUTF16("shipping.address.addressLine1"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address Line2"), ASCIIToUTF16("shipping.address.addressLine2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address Line1"), ASCIIToUTF16("billing.address.addressLine1"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address Line2"), ASCIIToUTF16("billing.address.addressLine2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); @@ -907,25 +1002,29 @@ TEST(FormStructureTest, ThreeAddressLinesExpedia) { ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_ads1"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Suite or Apt:"), ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_adap"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Street address second line"), ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_ads2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("City:"), ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_adct"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); @@ -954,19 +1053,22 @@ TEST(FormStructureTest, TwoAddressLinesEbay) { ASCIIToUTF16("address1"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Floor number, suite number, etc"), ASCIIToUTF16("address2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("City"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(3U, form_structure->field_count()); @@ -990,19 +1092,22 @@ TEST(FormStructureTest, HeuristicsStateWithProvince) { ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address Line2"), ASCIIToUTF16("Address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("State/Province/Region"), ASCIIToUTF16("State"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(3U, form_structure->field_count()); @@ -1027,67 +1132,78 @@ TEST(FormStructureTest, HeuristicsWithBilling) { ASCIIToUTF16("editBillingAddress$firstNameBox"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Last Name*:"), ASCIIToUTF16("editBillingAddress$lastNameBox"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Company Name:"), ASCIIToUTF16("editBillingAddress$companyBox"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Address*:"), ASCIIToUTF16("editBillingAddress$addressLine1Box"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Apt/Suite :"), ASCIIToUTF16("editBillingAddress$addressLine2Box"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("City*:"), ASCIIToUTF16("editBillingAddress$cityBox"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("State/Province*:"), ASCIIToUTF16("editBillingAddress$stateDropDown"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Country*:"), ASCIIToUTF16("editBillingAddress$countryDropDown"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Postal Code*:"), ASCIIToUTF16("editBillingAddress$zipCodeBox"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Phone*:"), ASCIIToUTF16("editBillingAddress$phoneBox"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("Email Address*:"), ASCIIToUTF16("email$emailBox"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(11U, form_structure->field_count()); @@ -1118,25 +1234,29 @@ TEST(FormStructureTest, ThreePartPhoneNumber) { ASCIIToUTF16("dayphone1"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("-"), ASCIIToUTF16("dayphone2"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("-"), ASCIIToUTF16("dayphone3"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back( webkit_glue::FormField(ASCIIToUTF16("ext.:"), ASCIIToUTF16("dayphone4"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); ASSERT_EQ(4U, form_structure->field_count()); @@ -1162,52 +1282,62 @@ TEST(FormStructureTest, MatchSpecificInputTypes) { ASCIIToUTF16("firstname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"), ASCIIToUTF16("email"), string16(), ASCIIToUTF16("email"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"), ASCIIToUTF16("phone"), string16(), ASCIIToUTF16("number"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Country"), ASCIIToUTF16("country"), string16(), ASCIIToUTF16("select-one"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"), ASCIIToUTF16("fax"), string16(), ASCIIToUTF16("tel"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), ASCIIToUTF16("address"), string16(), ASCIIToUTF16("radio"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("City"), ASCIIToUTF16("city"), string16(), ASCIIToUTF16("checkbox"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("State"), ASCIIToUTF16("state"), string16(), ASCIIToUTF16("hidden"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(string16(), ASCIIToUTF16("Submit"), string16(), ASCIIToUTF16("submit"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); @@ -1246,27 +1376,32 @@ TEST(FormStructureTest, HeuristicsInfernoCC) { ASCIIToUTF16("name_on_card"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), ASCIIToUTF16("billing_address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16("card_number"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Expiration Date"), ASCIIToUTF16("expiration_month"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Expiration Year"), ASCIIToUTF16("expiration_year"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form_structure.reset(new FormStructure(form)); EXPECT_TRUE(form_structure->IsAutoFillable(true)); @@ -1287,6 +1422,68 @@ TEST(FormStructureTest, HeuristicsInfernoCC) { form_structure->field(4)->heuristic_type()); } +TEST(FormStructureTest, CVCCodeClash) { + scoped_ptr<FormStructure> form_structure; + FormData form; + form.method = ASCIIToUTF16("post"); + form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Card number"), + ASCIIToUTF16("ccnumber"), + string16(), + ASCIIToUTF16("text"), + 0, + false)); + form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First name"), + ASCIIToUTF16("first_name"), + string16(), + ASCIIToUTF16("text"), + 0, + false)); + form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last name"), + ASCIIToUTF16("last_name"), + string16(), + ASCIIToUTF16("text"), + 0, + false)); + form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Expiration date"), + ASCIIToUTF16("ccexpiresmonth"), + string16(), + ASCIIToUTF16("text"), + 0, + false)); + form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16(""), + ASCIIToUTF16("ccexpiresyear"), + string16(), + ASCIIToUTF16("text"), + 0, + false)); + form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("cvc number"), + ASCIIToUTF16("csc"), + string16(), + ASCIIToUTF16("text"), + 0, + false)); + form_structure.reset(new FormStructure(form)); + EXPECT_TRUE(form_structure->IsAutoFillable(true)); + + // Expect the correct number of fields. + ASSERT_EQ(6U, form_structure->field_count()); + ASSERT_EQ(4U, form_structure->autofill_count()); + + // Card Number. + EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(0)->heuristic_type()); + // First name, taken as name on card. + EXPECT_EQ(CREDIT_CARD_NAME, form_structure->field(1)->heuristic_type()); + // Last name is not merged. + EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(2)->heuristic_type()); + // Expiration Date. + EXPECT_EQ(CREDIT_CARD_EXP_MONTH, form_structure->field(3)->heuristic_type()); + // Expiration Year. + EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR, + form_structure->field(4)->heuristic_type()); + // CVC code should not match. + EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(5)->heuristic_type()); +} + TEST(FormStructureTest, EncodeQueryRequest) { FormData form; form.method = ASCIIToUTF16("post"); @@ -1294,27 +1491,32 @@ TEST(FormStructureTest, EncodeQueryRequest) { ASCIIToUTF16("name_on_card"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), ASCIIToUTF16("billing_address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Card Number"), ASCIIToUTF16("card_number"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Expiration Date"), ASCIIToUTF16("expiration_month"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Expiration Year"), ASCIIToUTF16("expiration_year"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); ScopedVector<FormStructure> forms; forms.push_back(new FormStructure(form)); std::vector<std::string> encoded_signatures; @@ -1348,7 +1550,8 @@ TEST(FormStructureTest, EncodeQueryRequest) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); } forms.push_back(new FormStructure(form)); @@ -1380,7 +1583,8 @@ TEST(FormStructureTest, EncodeQueryRequest) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); } forms.push_back(new FormStructure(form)); @@ -1410,49 +1614,56 @@ TEST(FormStructureTest, EncodeUploadRequest) { ASCIIToUTF16("firstname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(NAME_FIRST); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("lastname"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(NAME_LAST); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"), ASCIIToUTF16("email"), string16(), ASCIIToUTF16("email"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(EMAIL_ADDRESS); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"), ASCIIToUTF16("phone"), string16(), ASCIIToUTF16("number"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(PHONE_HOME_WHOLE_NUMBER); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Country"), ASCIIToUTF16("country"), string16(), ASCIIToUTF16("select-one"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(ADDRESS_HOME_COUNTRY); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"), ASCIIToUTF16("fax"), string16(), ASCIIToUTF16("tel"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(PHONE_FAX_WHOLE_NUMBER); form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"), ASCIIToUTF16("address"), string16(), ASCIIToUTF16("radio"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(ADDRESS_HOME_LINE1); form_structure.reset(new FormStructure(form)); @@ -1488,7 +1699,8 @@ TEST(FormStructureTest, EncodeUploadRequest) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(ADDRESS_HOME_LINE1); possible_field_types.back().insert(ADDRESS_HOME_LINE2); @@ -1532,7 +1744,8 @@ TEST(FormStructureTest, EncodeUploadRequest) { ASCIIToUTF16("address"), string16(), ASCIIToUTF16("text"), - 0)); + 0, + false)); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(ADDRESS_HOME_LINE1); possible_field_types.back().insert(ADDRESS_HOME_LINE2); diff --git a/chrome/browser/autofill/name_field_unittest.cc b/chrome/browser/autofill/name_field_unittest.cc index 03cbec3..ce64c5f 100644 --- a/chrome/browser/autofill/name_field_unittest.cc +++ b/chrome/browser/autofill/name_field_unittest.cc @@ -32,21 +32,24 @@ TEST_F(NameFieldTest, FirstMiddleLast) { ASCIIToUTF16("First"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Middle Name"), ASCIIToUTF16("Middle"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("Last"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name3"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -70,21 +73,24 @@ TEST_F(NameFieldTest, FirstMiddleLast2) { ASCIIToUTF16("firstName"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("middleName"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("lastName"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name3"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -108,14 +114,16 @@ TEST_F(NameFieldTest, FirstLast) { ASCIIToUTF16("first_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("last_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -136,14 +144,16 @@ TEST_F(NameFieldTest, FirstLast2) { ASCIIToUTF16("first_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Name"), ASCIIToUTF16("last_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -164,21 +174,24 @@ TEST_F(NameFieldTest, FirstLastMiddleWithSpaces) { ASCIIToUTF16("first name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Middle Name"), ASCIIToUTF16("middle name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("last name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name3"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -202,14 +215,16 @@ TEST_F(NameFieldTest, FirstLastEmpty) { ASCIIToUTF16("first_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("last_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -230,21 +245,24 @@ TEST_F(NameFieldTest, FirstMiddleLastEmpty) { ASCIIToUTF16("first_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("middle_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("last_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name3"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -268,21 +286,24 @@ TEST_F(NameFieldTest, MiddleInitial) { ASCIIToUTF16("first_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("MI"), ASCIIToUTF16("middle_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Last Name"), ASCIIToUTF16("last_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name3"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -306,14 +327,16 @@ TEST_F(NameFieldTest, MiddleInitialNoLastName) { ASCIIToUTF16("first_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("MI"), ASCIIToUTF16("middle_name"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -329,21 +352,24 @@ TEST_F(NameFieldTest, MiddleInitialAtEnd) { ASCIIToUTF16("XXXnameXXXfirst"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("XXXnameXXXmi"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("XXXnameXXXlast"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name3"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -367,7 +393,8 @@ TEST_F(NameFieldTest, ECMLNoName) { ASCIIToUTF16("ecom_shipto_postal_company"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("field1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -381,14 +408,16 @@ TEST_F(NameFieldTest, ECMLMiddleInitialNoLastName) { ASCIIToUTF16("ecom_shipto_postal_name_first"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back(new AutoFillField( webkit_glue::FormField(ASCIIToUTF16("Middle"), ASCIIToUTF16("ecom_shipto_postal_name_middle"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -402,21 +431,24 @@ TEST_F(NameFieldTest, ECMLFirstMiddleLast) { ASCIIToUTF16("ecom_shipto_postal_name_first"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name1"))); list_.push_back(new AutoFillField( webkit_glue::FormField(string16(), ASCIIToUTF16("ecom_shipto_postal_name_middle"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name2"))); list_.push_back(new AutoFillField( webkit_glue::FormField(string16(), ASCIIToUTF16("ecom_shipto_postal_name_last"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("name3"))); list_.push_back(NULL); iter_ = list_.begin(); diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc index b6a99d8..c4b88bb 100644 --- a/chrome/browser/autofill/personal_data_manager.cc +++ b/chrome/browser/autofill/personal_data_manager.cc @@ -22,8 +22,10 @@ namespace { // The minimum number of fields that must contain user data and have known types -// before AutoFill will attempt to import the data into a profile. -const int kMinImportSize = 3; +// before AutoFill will attempt to import the data into a profile or a credit +// card. +const int kMinProfileImportSize = 3; +const int kMinCreditCardImportSize = 2; template<typename T> class FormGroupGUIDMatchesFunctor { @@ -212,28 +214,47 @@ bool PersonalDataManager::ImportFormData( string16 number; string16 city_code; string16 country_code; + PhoneNumber::ParsePhoneNumber(value, + &number, + &city_code, + &country_code); + if (number.empty()) + continue; + if (group == AutoFillType::PHONE_HOME) { - PhoneNumber::ParsePhoneNumber( - value, &number, &city_code, &country_code); - imported_profile_->SetInfo( - AutoFillType(PHONE_HOME_COUNTRY_CODE), country_code); - imported_profile_->SetInfo( - AutoFillType(PHONE_HOME_CITY_CODE), city_code); - imported_profile_->SetInfo( - AutoFillType(PHONE_HOME_NUMBER), number); + imported_profile_->SetInfo(AutoFillType(PHONE_HOME_COUNTRY_CODE), + country_code); + imported_profile_->SetInfo(AutoFillType(PHONE_HOME_CITY_CODE), + city_code); + imported_profile_->SetInfo(AutoFillType(PHONE_HOME_NUMBER), number); } else if (group == AutoFillType::PHONE_FAX) { - PhoneNumber::ParsePhoneNumber( - value, &number, &city_code, &country_code); - imported_profile_->SetInfo( - AutoFillType(PHONE_FAX_COUNTRY_CODE), country_code); - imported_profile_->SetInfo( - AutoFillType(PHONE_FAX_CITY_CODE), city_code); - imported_profile_->SetInfo( - AutoFillType(PHONE_FAX_NUMBER), number); + imported_profile_->SetInfo(AutoFillType(PHONE_FAX_COUNTRY_CODE), + country_code); + imported_profile_->SetInfo(AutoFillType(PHONE_FAX_CITY_CODE), + city_code); + imported_profile_->SetInfo(AutoFillType(PHONE_FAX_NUMBER), number); } + continue; } + // Phone and fax numbers can be split across multiple fields, so we + // might have already stored the prefix, and now be at the suffix. + // If so, combine them to form the full number. + if (group == AutoFillType::PHONE_HOME || + group == AutoFillType::PHONE_FAX) { + AutoFillType number_type(PHONE_HOME_NUMBER); + if (group == AutoFillType::PHONE_FAX) + number_type = AutoFillType(PHONE_FAX_NUMBER); + + string16 stored_number = imported_profile_->GetFieldText(number_type); + if (stored_number.size() == + static_cast<size_t>(PhoneNumber::kPrefixLength) && + value.size() == static_cast<size_t>(PhoneNumber::kSuffixLength)) { + value = stored_number + value; + } + } + imported_profile_->SetInfo(AutoFillType(field_type.field_type()), value); ++importable_fields; @@ -243,13 +264,9 @@ bool PersonalDataManager::ImportFormData( // If the user did not enter enough information on the page then don't bother // importing the data. - if (importable_fields + importable_credit_card_fields < kMinImportSize) - return false; - - if (importable_fields == 0) + if (importable_fields < kMinProfileImportSize) imported_profile_.reset(); - - if (importable_credit_card_fields == 0) + if (importable_credit_card_fields < kMinCreditCardImportSize) imported_credit_card_.reset(); if (imported_credit_card_.get()) { @@ -271,11 +288,17 @@ bool PersonalDataManager::ImportFormData( } } - // We always save imported profiles. - SaveImportedProfile(); + if (imported_profile_.get()) { + // We always save imported profiles. + SaveImportedProfile(); + } +<<<<<<< HEAD return true; #endif +======= + return imported_profile_.get() || imported_credit_card_.get(); +>>>>>>> Chromium.org at 9.0.597.55 } void PersonalDataManager::GetImportedFormData(AutoFillProfile** profile, @@ -612,35 +635,24 @@ bool PersonalDataManager::HasPassword() { const std::vector<AutoFillProfile*>& PersonalDataManager::profiles() { // |profile_| is NULL in AutoFillManagerTest. - if (!profile_) - return web_profiles_.get(); - - bool auxiliary_profiles_enabled = profile_->GetPrefs()->GetBoolean( - prefs::kAutoFillAuxiliaryProfilesEnabled); + bool auxiliary_profiles_enabled = profile_ ? profile_->GetPrefs()->GetBoolean( + prefs::kAutoFillAuxiliaryProfilesEnabled) : false; + if (!auxiliary_profiles_enabled) + return web_profiles(); #if !defined(OS_MACOSX) - DCHECK(!auxiliary_profiles_enabled) - << "Auxiliary profiles supported on Mac only"; + NOTREACHED() << "Auxiliary profiles supported on Mac only"; #endif - if (auxiliary_profiles_enabled) { - profiles_.clear(); + profiles_.clear(); - // Populates |auxiliary_profiles_|. - LoadAuxiliaryProfiles(); - - profiles_.insert(profiles_.end(), - web_profiles_.begin(), web_profiles_.end()); - profiles_.insert(profiles_.end(), - auxiliary_profiles_.begin(), auxiliary_profiles_.end()); - return profiles_; - } else { - return web_profiles_.get(); - } -} + // Populates |auxiliary_profiles_|. + LoadAuxiliaryProfiles(); -const std::vector<AutoFillProfile*>& PersonalDataManager::web_profiles() { - return web_profiles_.get(); + profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end()); + profiles_.insert(profiles_.end(), + auxiliary_profiles_.begin(), auxiliary_profiles_.end()); + return profiles_; } AutoFillProfile* PersonalDataManager::CreateNewEmptyAutoFillProfileForDBThread( diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h index 114c109..8d79315 100644 --- a/chrome/browser/autofill/personal_data_manager.h +++ b/chrome/browser/autofill/personal_data_manager.h @@ -139,7 +139,9 @@ class PersonalDataManager // card information, respectively. |profiles()| returns both web and // auxiliary profiles. |web_profiles()| returns only web profiles. const std::vector<AutoFillProfile*>& profiles(); - virtual const std::vector<AutoFillProfile*>& web_profiles(); + virtual const std::vector<AutoFillProfile*>& web_profiles() { + return web_profiles_.get(); + } virtual const std::vector<CreditCard*>& credit_cards() { return credit_cards_.get(); } diff --git a/chrome/browser/autofill/personal_data_manager_unittest.cc b/chrome/browser/autofill/personal_data_manager_unittest.cc index 7c2fc5f..a4b3099 100644 --- a/chrome/browser/autofill/personal_data_manager_unittest.cc +++ b/chrome/browser/autofill/personal_data_manager_unittest.cc @@ -526,7 +526,7 @@ TEST_F(PersonalDataManagerTest, ImportFormData) { FormStructure form_structure(form); std::vector<FormStructure*> forms; forms.push_back(&form_structure); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -543,6 +543,73 @@ TEST_F(PersonalDataManagerTest, ImportFormData) { EXPECT_EQ(0, expected.Compare(*results[0])); } +TEST_F(PersonalDataManagerTest, ImportFormDataNotEnoughFilledFields) { + FormData form; + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form.fields.push_back(field); + autofill_test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form.fields.push_back(field); + autofill_test::CreateTestFormField( + "Card number:", "card_number", "4111 1111 1111 1111", "text", &field); + form.fields.push_back(field); + FormStructure form_structure(form); + std::vector<FormStructure*> forms; + forms.push_back(&form_structure); + EXPECT_FALSE(personal_data_->ImportFormData(forms)); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles(); + ASSERT_EQ(0U, profiles.size()); + const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards(); + ASSERT_EQ(0U, credit_cards.size()); +} + +TEST_F(PersonalDataManagerTest, ImportPhoneNumberSplitAcrossMultipleFields) { + FormData form; + webkit_glue::FormField field; + autofill_test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form.fields.push_back(field); + autofill_test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form.fields.push_back(field); + autofill_test::CreateTestFormField( + "Phone #:", "home_phone_area_code", "650", "text", &field); + field.set_max_length(3); + form.fields.push_back(field); + autofill_test::CreateTestFormField( + "Phone #:", "home_phone_prefix", "555", "text", &field); + field.set_max_length(3); + form.fields.push_back(field); + autofill_test::CreateTestFormField( + "Phone #:", "home_phone_suffix", "0000", "text", &field); + field.set_max_length(4); + form.fields.push_back(field); + FormStructure form_structure(form); + std::vector<FormStructure*> forms; + forms.push_back(&form_structure); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); + + // Wait for the refresh. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop()); + + MessageLoop::current()->Run(); + + AutoFillProfile expected; + autofill_test::SetProfileInfo(&expected, NULL, "George", NULL, "Washington", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "6505550000", NULL); + const std::vector<AutoFillProfile*>& results = personal_data_->profiles(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); +} + TEST_F(PersonalDataManagerTest, SetUniqueCreditCardLabels) { CreditCard credit_card0; credit_card0.set_label(ASCIIToUTF16("Home")); @@ -620,7 +687,7 @@ TEST_F(PersonalDataManagerTest, AggregateTwoDifferentProfiles) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -651,7 +718,7 @@ TEST_F(PersonalDataManagerTest, AggregateTwoDifferentProfiles) { FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -683,13 +750,20 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { "Address:", "address", "1600 Pennsylvania Avenue", "text", &field); form1.fields.push_back(field); autofill_test::CreateTestFormField( + "Address Line 2:", "address2", "Suite A", "text", &field); + form1.fields.push_back(field); + autofill_test::CreateTestFormField( "Email:", "email", "theprez@gmail.com", "text", &field); form1.fields.push_back(field); + // Phone gets updated. + autofill_test::CreateTestFormField( + "Phone:", "phone", "4445556666", "text", &field); + form1.fields.push_back(field); FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -699,8 +773,8 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { AutoFillProfile expected; autofill_test::SetProfileInfo(&expected, NULL, "George", NULL, - "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue", NULL, - NULL, NULL, NULL, NULL, NULL, NULL); + "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue", + "Suite A", NULL, NULL, NULL, NULL, "4445556666", NULL); const std::vector<AutoFillProfile*>& results1 = personal_data_->profiles(); ASSERT_EQ(1U, results1.size()); EXPECT_EQ(0, expected.Compare(*results1[0])); @@ -716,19 +790,25 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { autofill_test::CreateTestFormField( "Address:", "address", "1600 Pennsylvania Avenue", "text", &field); form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Address Line 2:", "address2", "Suite A", "text", &field); + form2.fields.push_back(field); + autofill_test::CreateTestFormField( + "Email:", "email", "theprez@gmail.com", "text", &field); + form2.fields.push_back(field); // Country gets added. autofill_test::CreateTestFormField( "Country:", "country", "USA", "text", &field); form2.fields.push_back(field); - // Email gets updated. + // Phone gets updated. autofill_test::CreateTestFormField( - "Email:", "email", "new_email@gmail.com", "text", &field); + "Phone:", "phone", "1231231234", "text", &field); form2.fields.push_back(field); FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -740,8 +820,8 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { AutoFillProfile expected2; autofill_test::SetProfileInfo(&expected2, NULL, "George", NULL, - "Washington", "new_email@gmail.com", NULL, "1600 Pennsylvania Avenue", - NULL, NULL, NULL, NULL, "USA", NULL, NULL); + "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue", + "Suite A", NULL, NULL, NULL, "USA", "1231231234", NULL); ASSERT_EQ(1U, results2.size()); EXPECT_EQ(0, expected2.Compare(*results2[0])); } @@ -762,7 +842,7 @@ TEST_F(PersonalDataManagerTest, AggregateProfileWithMissingInfoInOld) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -802,7 +882,7 @@ TEST_F(PersonalDataManagerTest, AggregateProfileWithMissingInfoInOld) { FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -839,7 +919,7 @@ TEST_F(PersonalDataManagerTest, AggregateProfileWithMissingInfoInNew) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -871,7 +951,7 @@ TEST_F(PersonalDataManagerTest, AggregateProfileWithMissingInfoInNew) { FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); // Wait for the refresh. EXPECT_CALL(personal_data_observer_, @@ -907,7 +987,7 @@ TEST_F(PersonalDataManagerTest, AggregateTwoDifferentCreditCards) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -941,7 +1021,7 @@ TEST_F(PersonalDataManagerTest, AggregateTwoDifferentCreditCards) { FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -980,7 +1060,7 @@ TEST_F(PersonalDataManagerTest, AggregateInvalidCreditCard) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -1014,7 +1094,7 @@ TEST_F(PersonalDataManagerTest, AggregateInvalidCreditCard) { FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_FALSE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Note: no refresh here. @@ -1045,7 +1125,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameCreditCardWithConflict) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -1080,7 +1160,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameCreditCardWithConflict) { FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -1120,7 +1200,7 @@ TEST_F(PersonalDataManagerTest, AggregateEmptyCreditCardWithConflict) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -1186,7 +1266,7 @@ TEST_F(PersonalDataManagerTest, AggregateCreditCardWithMissingInfoInNew) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -1252,7 +1332,7 @@ TEST_F(PersonalDataManagerTest, AggregateCreditCardWithMissingInfoInOld) { FormStructure form_structure1(form1); std::vector<FormStructure*> forms; forms.push_back(&form_structure1); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. @@ -1287,7 +1367,7 @@ TEST_F(PersonalDataManagerTest, AggregateCreditCardWithMissingInfoInOld) { FormStructure form_structure2(form2); forms.clear(); forms.push_back(&form_structure2); - personal_data_->ImportFormData(forms); + EXPECT_TRUE(personal_data_->ImportFormData(forms)); personal_data_->SaveImportedCreditCard(); // Wait for the refresh. diff --git a/chrome/browser/autofill/phone_field_unittest.cc b/chrome/browser/autofill/phone_field_unittest.cc index ce0ae48..e79d64a 100644 --- a/chrome/browser/autofill/phone_field_unittest.cc +++ b/chrome/browser/autofill/phone_field_unittest.cc @@ -46,7 +46,8 @@ TEST_F(PhoneFieldTest, ParseOneLinePhone) { ASCIIToUTF16("phone"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("phone1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -64,7 +65,8 @@ TEST_F(PhoneFieldTest, ParseOneLinePhoneEcml) { ASCIIToUTF16(kEcmlShipToPhone), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("phone1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -82,14 +84,16 @@ TEST_F(PhoneFieldTest, ParseTwoLinePhone) { ASCIIToUTF16("area code"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("areacode1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Phone"), ASCIIToUTF16("phone"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("phone1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -111,14 +115,16 @@ TEST_F(PhoneFieldTest, ParseTwoLinePhoneEcmlShipTo) { ASCIIToUTF16(kEcmlShipToPostalCode), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("areacode1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Phone"), ASCIIToUTF16(kEcmlShipToPhone), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("phone1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -140,14 +146,16 @@ TEST_F(PhoneFieldTest, ParseTwoLinePhoneEcmlBillTo) { ASCIIToUTF16(kEcmlBillToPostalCode), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("areacode1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Phone"), ASCIIToUTF16(kEcmlBillToPhone), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("phone1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -168,28 +176,32 @@ TEST_F(PhoneFieldTest, ThreePartPhoneNumber) { ASCIIToUTF16("dayphone1"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("areacode1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("-"), ASCIIToUTF16("dayphone2"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("prefix1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("-"), ASCIIToUTF16("dayphone3"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("suffix1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("ext.:"), ASCIIToUTF16("dayphone4"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("ext1"))); list_.push_back(NULL); iter_ = list_.begin(); @@ -216,21 +228,24 @@ TEST_F(PhoneFieldTest, ThreePartPhoneNumberPrefixSuffix) { ASCIIToUTF16("area"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("areacode1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("prefix"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("prefix1"))); list_.push_back( new AutoFillField(webkit_glue::FormField(string16(), ASCIIToUTF16("suffix"), string16(), ASCIIToUTF16("text"), - 0), + 0, + false), ASCIIToUTF16("suffix1"))); list_.push_back(NULL); iter_ = list_.begin(); diff --git a/chrome/browser/autofill/phone_number.h b/chrome/browser/autofill/phone_number.h index 1167683..277e1b1 100644 --- a/chrome/browser/autofill/phone_number.h +++ b/chrome/browser/autofill/phone_number.h @@ -38,6 +38,12 @@ class PhoneNumber : public FormGroup { string16* city_code, string16* country_code); + // Size and offset of the prefix and suffix portions of phone numbers. + static const int kPrefixOffset = 0; + static const int kPrefixLength = 3; + static const int kSuffixOffset = 3; + static const int kSuffixLength = 4; + protected: explicit PhoneNumber(const PhoneNumber& phone_number); |