form_field.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/autofill/form_field.h" 6 7<<<<<<< HEAD 8#ifdef ANDROID 9#include "app/l10n_util.h" 10#endif 11======= 12#include "app/l10n_util.h" 13>>>>>>> chromium.org at r10.0.634.0 14#include "base/string_util.h" 15#include "base/utf_string_conversions.h" 16#include "chrome/browser/autofill/address_field.h" 17#include "chrome/browser/autofill/autofill_field.h" 18#include "chrome/browser/autofill/credit_card_field.h" 19#include "chrome/browser/autofill/fax_field.h" 20#include "chrome/browser/autofill/name_field.h" 21#include "chrome/browser/autofill/phone_field.h" 22#include "third_party/WebKit/WebKit/chromium/public/WebRegularExpression.h" 23#include "third_party/WebKit/WebKit/chromium/public/WebString.h" 24#include "grit/autofill_resources.h" 25 26// Field names from the ECML specification; see RFC 3106. We've 27// made these names lowercase since we convert labels and field names to 28// lowercase before searching. 29 30// shipping name/address fields 31const char kEcmlShipToTitle[] = "ecom_shipto_postal_name_prefix"; 32const char kEcmlShipToFirstName[] = "ecom_shipto_postal_name_first"; 33const char kEcmlShipToMiddleName[] = "ecom_shipto_postal_name_middle"; 34const char kEcmlShipToLastName[] = "ecom_shipto_postal_name_last"; 35const char kEcmlShipToNameSuffix[] = "ecom_shipto_postal_name_suffix"; 36const char kEcmlShipToCompanyName[] = "ecom_shipto_postal_company"; 37const char kEcmlShipToAddress1[] = "ecom_shipto_postal_street_line1"; 38const char kEcmlShipToAddress2[] = "ecom_shipto_postal_street_line2"; 39const char kEcmlShipToAddress3[] = "ecom_shipto_postal_street_line3"; 40const char kEcmlShipToCity[] = "ecom_shipto_postal_city"; 41const char kEcmlShipToStateProv[] = "ecom_shipto_postal_stateprov"; 42const char kEcmlShipToPostalCode[] = "ecom_shipto_postal_postalcode"; 43const char kEcmlShipToCountry[] = "ecom_shipto_postal_countrycode"; 44const char kEcmlShipToPhone[] = "ecom_shipto_telecom_phone_number"; 45const char kEcmlShipToEmail[] = "ecom_shipto_online_email"; 46 47// billing name/address fields 48const char kEcmlBillToTitle[] = "ecom_billto_postal_name_prefix"; 49const char kEcmlBillToFirstName[] = "ecom_billto_postal_name_first"; 50const char kEcmlBillToMiddleName[] = "ecom_billto_postal_name_middle"; 51const char kEcmlBillToLastName[] = "ecom_billto_postal_name_last"; 52const char kEcmlBillToNameSuffix[] = "ecom_billto_postal_name_suffix"; 53const char kEcmlBillToCompanyName[] = "ecom_billto_postal_company"; 54const char kEcmlBillToAddress1[] = "ecom_billto_postal_street_line1"; 55const char kEcmlBillToAddress2[] = "ecom_billto_postal_street_line2"; 56const char kEcmlBillToAddress3[] = "ecom_billto_postal_street_line3"; 57const char kEcmlBillToCity[] = "ecom_billto_postal_city"; 58const char kEcmlBillToStateProv[] = "ecom_billto_postal_stateprov"; 59const char kEcmlBillToPostalCode[] = "ecom_billto_postal_postalcode"; 60const char kEcmlBillToCountry[] = "ecom_billto_postal_countrycode"; 61const char kEcmlBillToPhone[] = "ecom_billto_telecom_phone_number"; 62const char kEcmlBillToEmail[] = "ecom_billto_online_email"; 63 64// credit card fields 65const char kEcmlCardHolder[] = "ecom_payment_card_name"; 66const char kEcmlCardType[] = "ecom_payment_card_type"; 67const char kEcmlCardNumber[] = "ecom_payment_card_number"; 68const char kEcmlCardVerification[] = "ecom_payment_card_verification"; 69const char kEcmlCardExpireDay[] = "ecom_payment_card_expdate_day"; 70const char kEcmlCardExpireMonth[] = "ecom_payment_card_expdate_month"; 71const char kEcmlCardExpireYear[] = "ecom_payment_card_expdate_year"; 72 73namespace { 74 75// The name of the hidden form control element. 76const char* const kControlTypeHidden = "hidden"; 77 78// The name of the radio form control element. 79const char* const kControlTypeRadio = "radio"; 80 81// The name of the checkbox form control element. 82const char* const kControlTypeCheckBox = "checkbox"; 83 84} // namespace 85 86class EmailField : public FormField { 87 public: 88 virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const { 89 bool ok = Add(field_type_map, field_, AutoFillType(EMAIL_ADDRESS)); 90 DCHECK(ok); 91 return true; 92 } 93 94 static EmailField* Parse(std::vector<AutoFillField*>::const_iterator* iter, 95 bool is_ecml) { 96 string16 pattern; 97 if (is_ecml) { 98 pattern = GetEcmlPattern(kEcmlShipToEmail, kEcmlBillToEmail, '|'); 99 } else { 100 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EMAIL_RE); 101 } 102 103 AutoFillField* field; 104 if (ParseText(iter, pattern, &field)) 105 return new EmailField(field); 106 107 return NULL; 108 } 109 110 private: 111 explicit EmailField(AutoFillField *field) : field_(field) {} 112 113 AutoFillField* field_; 114}; 115 116FormFieldType FormField::GetFormFieldType() const { 117 return kOtherFieldType; 118} 119 120// static 121bool FormField::Match(AutoFillField* field, 122 const string16& pattern, 123 bool match_label_only) { 124 if (match_label_only) { 125 if (MatchLabel(field, pattern)) { 126 return true; 127 } 128 } else { 129 // For now, we apply the same pattern to the field's label and the field's 130 // name. Matching the name is a bit of a long shot for many patterns, but 131 // it generally doesn't hurt to try. 132 if (MatchLabel(field, pattern) || MatchName(field, pattern)) { 133 return true; 134 } 135 } 136 137 return false; 138} 139 140// static 141bool FormField::MatchName(AutoFillField* field, const string16& pattern) { 142 // TODO(jhawkins): Remove StringToLowerASCII. WebRegularExpression needs to 143 // be fixed to take WebTextCaseInsensitive into account. 144 WebKit::WebRegularExpression re(WebKit::WebString(pattern), 145 WebKit::WebTextCaseInsensitive); 146 bool match = re.match( 147 WebKit::WebString(StringToLowerASCII(field->name()))) != -1; 148 return match; 149} 150 151// static 152bool FormField::MatchLabel(AutoFillField* field, const string16& pattern) { 153 // TODO(jhawkins): Remove StringToLowerASCII. WebRegularExpression needs to 154 // be fixed to take WebTextCaseInsensitive into account. 155 WebKit::WebRegularExpression re(WebKit::WebString(pattern), 156 WebKit::WebTextCaseInsensitive); 157 bool match = re.match( 158 WebKit::WebString(StringToLowerASCII(field->label()))) != -1; 159 return match; 160} 161 162// static 163FormField* FormField::ParseFormField( 164 std::vector<AutoFillField*>::const_iterator* iter, 165 bool is_ecml) { 166 FormField *field; 167 field = EmailField::Parse(iter, is_ecml); 168 if (field != NULL) 169 return field; 170 field = PhoneField::Parse(iter, is_ecml); 171 if (field != NULL) 172 return field; 173 field = FaxField::Parse(iter); 174 if (field != NULL) 175 return field; 176 field = AddressField::Parse(iter, is_ecml); 177 if (field != NULL) 178 return field; 179 field = CreditCardField::Parse(iter, is_ecml); 180 if (field != NULL) 181 return field; 182 183 // We search for a NameField last since it matches the word "name", which is 184 // relatively general. 185 return NameField::Parse(iter, is_ecml); 186} 187 188// static 189bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter, 190 const string16& pattern) { 191 AutoFillField* field; 192 return ParseText(iter, pattern, &field); 193} 194 195// static 196bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter, 197 const string16& pattern, 198 AutoFillField** dest) { 199 return ParseText(iter, pattern, dest, false); 200} 201 202// static 203bool FormField::ParseEmptyText( 204 std::vector<AutoFillField*>::const_iterator* iter, 205 AutoFillField** dest) { 206 return ParseLabelText(iter, ASCIIToUTF16("^$"), dest); 207} 208 209// static 210bool FormField::ParseLabelText( 211 std::vector<AutoFillField*>::const_iterator* iter, 212 const string16& pattern, 213 AutoFillField** dest) { 214 return ParseText(iter, pattern, dest, true); 215} 216 217// static 218bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter, 219 const string16& pattern, 220 AutoFillField** dest, 221 bool match_label_only) { 222 // Some forms have one or more hidden fields before each visible input; skip 223 // past these. 224 while (**iter && LowerCaseEqualsASCII((**iter)->form_control_type(), 225 kControlTypeHidden)) 226 (*iter)++; 227 228 AutoFillField* field = **iter; 229 if (!field) 230 return false; 231 232 if (Match(field, pattern, match_label_only)) { 233 if (dest) 234 *dest = field; 235 (*iter)++; 236 return true; 237 } 238 239 return false; 240} 241 242// static 243bool FormField::ParseLabelAndName( 244 std::vector<AutoFillField*>::const_iterator* iter, 245 const string16& pattern, 246 AutoFillField** dest) { 247 AutoFillField* field = **iter; 248 if (!field) 249 return false; 250 251 if (MatchLabel(field, pattern) && MatchName(field, pattern)) { 252 if (dest) 253 *dest = field; 254 (*iter)++; 255 return true; 256 } 257 258 return false; 259} 260 261// static 262bool FormField::ParseEmpty(std::vector<AutoFillField*>::const_iterator* iter) { 263 // TODO(jhawkins): Handle select fields. 264 return ParseLabelAndName(iter, ASCIIToUTF16("^$"), NULL); 265} 266 267// static 268bool FormField::Add(FieldTypeMap* field_type_map, AutoFillField* field, 269 const AutoFillType& type) { 270 // Several fields are optional. 271 if (field) 272 field_type_map->insert(make_pair(field->unique_name(), type.field_type())); 273 274 return true; 275} 276 277string16 FormField::GetEcmlPattern(const char* ecml_name) { 278 return ASCIIToUTF16(std::string("^") + ecml_name); 279} 280 281string16 FormField::GetEcmlPattern(const char* ecml_name1, 282 const char* ecml_name2, 283 char pattern_operator) { 284 return ASCIIToUTF16(StringPrintf("^%s%c^%s", 285 ecml_name1, pattern_operator, ecml_name2)); 286} 287 288FormFieldSet::FormFieldSet(FormStructure* fields) { 289 std::vector<AddressField*> addresses; 290 291 // First, find if there is one form field with an ECML name. If there is, 292 // then we will match an element only if it is in the standard. 293 bool is_ecml = CheckECML(fields); 294 295 // Parse fields. 296 std::vector<AutoFillField*>::const_iterator field = fields->begin(); 297 while (field != fields->end() && *field != NULL) { 298 // Don't parse hidden fields or radio or checkbox controls. 299 if (LowerCaseEqualsASCII((*field)->form_control_type(), 300 kControlTypeHidden) || 301 LowerCaseEqualsASCII((*field)->form_control_type(), 302 kControlTypeRadio) || 303 LowerCaseEqualsASCII((*field)->form_control_type(), 304 kControlTypeCheckBox)) { 305 field++; 306 continue; 307 } 308 309 FormField* form_field = FormField::ParseFormField(&field, is_ecml); 310 if (!form_field) { 311 field++; 312 continue; 313 } 314 315 push_back(form_field); 316 317 if (form_field->GetFormFieldType() == kAddressType) { 318 AddressField* address = static_cast<AddressField*>(form_field); 319 if (address->IsFullAddress()) 320 addresses.push_back(address); 321 } 322 } 323 324 // Now determine an address type for each address. Note, if this is an ECML 325 // form, then we already got this info from the field names. 326 if (!is_ecml && !addresses.empty()) { 327 if (addresses.size() == 1) { 328 addresses[0]->SetType(addresses[0]->FindType()); 329 } else { 330 AddressType type0 = addresses[0]->FindType(); 331 AddressType type1 = addresses[1]->FindType(); 332 333 // When there are two addresses on a page, they almost always appear in 334 // the order (billing, shipping). 335 bool reversed = (type0 == kShippingAddress && type1 == kBillingAddress); 336 addresses[0]->SetType(reversed ? kShippingAddress : kBillingAddress); 337 addresses[1]->SetType(reversed ? kBillingAddress : kShippingAddress); 338 } 339 } 340} 341 342bool FormFieldSet::CheckECML(FormStructure* fields) { 343 size_t num_fields = fields->field_count(); 344 struct EcmlField { 345 const char* name_; 346 const int length_; 347 } form_fields[] = { 348#define ECML_STRING_ENTRY(x) { x, arraysize(x) - 1 }, 349 ECML_STRING_ENTRY(kEcmlShipToTitle) 350 ECML_STRING_ENTRY(kEcmlShipToFirstName) 351 ECML_STRING_ENTRY(kEcmlShipToMiddleName) 352 ECML_STRING_ENTRY(kEcmlShipToLastName) 353 ECML_STRING_ENTRY(kEcmlShipToNameSuffix) 354 ECML_STRING_ENTRY(kEcmlShipToCompanyName) 355 ECML_STRING_ENTRY(kEcmlShipToAddress1) 356 ECML_STRING_ENTRY(kEcmlShipToAddress2) 357 ECML_STRING_ENTRY(kEcmlShipToAddress3) 358 ECML_STRING_ENTRY(kEcmlShipToCity) 359 ECML_STRING_ENTRY(kEcmlShipToStateProv) 360 ECML_STRING_ENTRY(kEcmlShipToPostalCode) 361 ECML_STRING_ENTRY(kEcmlShipToCountry) 362 ECML_STRING_ENTRY(kEcmlShipToPhone) 363 ECML_STRING_ENTRY(kEcmlShipToPhone) 364 ECML_STRING_ENTRY(kEcmlShipToEmail) 365 ECML_STRING_ENTRY(kEcmlBillToTitle) 366 ECML_STRING_ENTRY(kEcmlBillToFirstName) 367 ECML_STRING_ENTRY(kEcmlBillToMiddleName) 368 ECML_STRING_ENTRY(kEcmlBillToLastName) 369 ECML_STRING_ENTRY(kEcmlBillToNameSuffix) 370 ECML_STRING_ENTRY(kEcmlBillToCompanyName) 371 ECML_STRING_ENTRY(kEcmlBillToAddress1) 372 ECML_STRING_ENTRY(kEcmlBillToAddress2) 373 ECML_STRING_ENTRY(kEcmlBillToAddress3) 374 ECML_STRING_ENTRY(kEcmlBillToCity) 375 ECML_STRING_ENTRY(kEcmlBillToStateProv) 376 ECML_STRING_ENTRY(kEcmlBillToPostalCode) 377 ECML_STRING_ENTRY(kEcmlBillToCountry) 378 ECML_STRING_ENTRY(kEcmlBillToPhone) 379 ECML_STRING_ENTRY(kEcmlBillToPhone) 380 ECML_STRING_ENTRY(kEcmlBillToEmail) 381 ECML_STRING_ENTRY(kEcmlCardHolder) 382 ECML_STRING_ENTRY(kEcmlCardType) 383 ECML_STRING_ENTRY(kEcmlCardNumber) 384 ECML_STRING_ENTRY(kEcmlCardVerification) 385 ECML_STRING_ENTRY(kEcmlCardExpireMonth) 386 ECML_STRING_ENTRY(kEcmlCardExpireYear) 387#undef ECML_STRING_ENTRY 388 }; 389 390 const string16 ecom(ASCIIToUTF16("ecom")); 391 for (size_t index = 0; index < num_fields; ++index) { 392 const string16& utf16_name = fields->field(index)->name(); 393 if (StartsWith(utf16_name, ecom, true)) { 394 std::string name(UTF16ToASCII(utf16_name)); 395 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(form_fields); ++i) { 396 if (base::strncasecmp(name.c_str(), form_fields[i].name_, 397 form_fields[i].length_) == 0) { 398 return true; 399 } 400 } 401 } 402 } 403 404 return false; 405} 406