autofill_data_model.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// found in the LICENSE file. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/autofill_data_model.h" 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/basictypes.h" 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/logging.h" 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_util.h" 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/autofill_country.h" 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/autofill_field.h" 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/state_names.h" 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/validation.h" 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/common/form_field_data.h" 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "googleurl/src/gurl.h" 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "grit/component_strings.h" 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace autofill { 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace { 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char* const kMonthsAbbreviated[] = { 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) NULL, // Padding so index 1 = month 1 = January. 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Jan", "Feb", "Mar", "Apr", "May", "Jun", 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 28e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}; 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)const char* const kMonthsFull[] = { 31e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) NULL, // Padding so index 1 = month 1 = January. 325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) "January", "February", "March", "April", "May", "June", 331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) "July", "August", "September", "October", "November", "December", 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 35c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char* const kMonthsNumeric[] = { 37d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) NULL, // Padding so index 1 = month 1 = January. 38d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// Returns true if the value was successfully set, meaning |value| was found in 425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// the list of select options in |field|. 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SetSelectControlValue(const base::string16& value, 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FormFieldData* field) { 455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) base::string16 value_lowercase = StringToLowerASCII(value); 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) DCHECK_EQ(field->option_values.size(), field->option_contents.size()); 483c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch for (size_t i = 0; i < field->option_values.size(); ++i) { 4902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch if (value_lowercase == StringToLowerASCII(field->option_values[i]) || 503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch value_lowercase == StringToLowerASCII(field->option_contents[i])) { 51e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) field->value = field->option_values[i]; 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 533c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch } 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 563c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch return false; 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 58d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 59d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)bool FillStateSelectControl(const base::string16& value, 6002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch FormFieldData* field) { 613c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch base::string16 full, abbreviation; 623c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch state_names::GetNameAndAbbreviation(value, &full, &abbreviation); 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Try the abbreviation first. 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!abbreviation.empty() && SetSelectControlValue(abbreviation, field)) 66c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return true; 67 68 return !full.empty() && SetSelectControlValue(full, field); 69} 70 71bool FillExpirationMonthSelectControl(const base::string16& value, 72 FormFieldData* field) { 73 int index = 0; 74 if (!base::StringToInt(value, &index) || 75 index <= 0 || 76 static_cast<size_t>(index) >= arraysize(kMonthsFull)) 77 return false; 78 79 bool filled = 80 SetSelectControlValue(ASCIIToUTF16(kMonthsAbbreviated[index]), field) || 81 SetSelectControlValue(ASCIIToUTF16(kMonthsFull[index]), field) || 82 SetSelectControlValue(ASCIIToUTF16(kMonthsNumeric[index]), field); 83 return filled; 84} 85 86// Try to fill a credit card type |value| (Visa, MasterCard, etc.) into the 87// given |field|. 88bool FillCreditCardTypeSelectControl(const base::string16& value, 89 FormFieldData* field) { 90 // Try stripping off spaces. 91 base::string16 value_stripped; 92 RemoveChars(StringToLowerASCII(value), kWhitespaceUTF16, &value_stripped); 93 94 for (size_t i = 0; i < field->option_values.size(); ++i) { 95 base::string16 option_value_lowercase; 96 RemoveChars(StringToLowerASCII(field->option_values[i]), kWhitespaceUTF16, 97 &option_value_lowercase); 98 base::string16 option_contents_lowercase; 99 RemoveChars(StringToLowerASCII(field->option_contents[i]), kWhitespaceUTF16, 100 &option_contents_lowercase); 101 102 // Perform a case-insensitive comparison; but fill the form with the 103 // original text, not the lowercased version. 104 if (value_stripped == option_value_lowercase || 105 value_stripped == option_contents_lowercase) { 106 field->value = field->option_values[i]; 107 return true; 108 } 109 } 110 111 // For American Express, also try filling as "AmEx". 112 if (value == l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX)) 113 return FillCreditCardTypeSelectControl(ASCIIToUTF16("AmEx"), field); 114 115 return false; 116} 117 118} // namespace 119 120AutofillDataModel::AutofillDataModel(const std::string& guid, 121 const std::string& origin) 122 : guid_(guid), 123 origin_(origin) {} 124AutofillDataModel::~AutofillDataModel() {} 125 126void AutofillDataModel::FillSelectControl(AutofillFieldType type, 127 const std::string& app_locale, 128 FormFieldData* field) const { 129 DCHECK(field); 130 DCHECK_EQ("select-one", field->form_control_type); 131 DCHECK_EQ(field->option_values.size(), field->option_contents.size()); 132 133 base::string16 field_text = GetInfo(type, app_locale); 134 base::string16 field_text_lower = StringToLowerASCII(field_text); 135 if (field_text.empty()) 136 return; 137 138 base::string16 value; 139 for (size_t i = 0; i < field->option_values.size(); ++i) { 140 if (field_text == field->option_values[i] || 141 field_text == field->option_contents[i]) { 142 // An exact match, use it. 143 value = field->option_values[i]; 144 break; 145 } 146 147 if (field_text_lower == StringToLowerASCII(field->option_values[i]) || 148 field_text_lower == StringToLowerASCII(field->option_contents[i])) { 149 // A match, but not in the same case. Save it in case an exact match is 150 // not found. 151 value = field->option_values[i]; 152 } 153 } 154 155 if (!value.empty()) { 156 field->value = value; 157 return; 158 } 159 160 if (type == ADDRESS_HOME_STATE || type == ADDRESS_BILLING_STATE) { 161 FillStateSelectControl(field_text, field); 162 } else if (type == ADDRESS_HOME_COUNTRY || type == ADDRESS_BILLING_COUNTRY) { 163 FillCountrySelectControl(app_locale, field); 164 } else if (type == CREDIT_CARD_EXP_MONTH) { 165 FillExpirationMonthSelectControl(field_text, field); 166 } else if (type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { 167 // Attempt to fill the year as a 2-digit year. This compensates for the 168 // fact that our heuristics do not always correctly detect when a website 169 // requests a 2-digit rather than a 4-digit year. 170 FillSelectControl(CREDIT_CARD_EXP_2_DIGIT_YEAR, app_locale, field); 171 } else if (type == CREDIT_CARD_TYPE) { 172 FillCreditCardTypeSelectControl(field_text, field); 173 } 174} 175 176bool AutofillDataModel::FillCountrySelectControl( 177 const std::string& app_locale, 178 FormFieldData* field_data) const { 179 return false; 180} 181 182bool AutofillDataModel::IsVerified() const { 183 return !origin_.empty() && !GURL(origin_).is_valid(); 184} 185 186} // namespace autofill 187