name_field.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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/name_field.h" 6 7#include "base/scoped_ptr.h" 8#include "base/string_util.h" 9#include "base/utf_string_conversions.h" 10#include "chrome/browser/autofill/autofill_type.h" 11 12NameField* NameField::Parse(std::vector<AutoFillField*>::const_iterator* iter, 13 bool is_ecml) { 14 // Try FirstLastNameField first since it's more specific. 15 NameField* field = FirstLastNameField::Parse(iter, is_ecml); 16 if (field == NULL && !is_ecml) 17 field = FullNameField::Parse(iter); 18 return field; 19} 20 21FullNameField* FullNameField::Parse( 22 std::vector<AutoFillField*>::const_iterator* iter) { 23 // Exclude labels containing the string "username", which typically 24 // denotes a login ID rather than the user's actual name. 25 AutoFillField* field = **iter; 26 if (Match(field, ASCIIToUTF16("username"), false)) 27 return NULL; 28 29 // Searching for any label containing the word "name" is too general; 30 // for example, Travelocity_Edit travel profile.html contains a field 31 // "Travel Profile Name". 32 const string16 name_match = 33 ASCIIToUTF16("^name|full *name|your name|customer name"); 34 if (ParseText(iter, name_match, &field)) 35 return new FullNameField(field); 36 37 return NULL; 38} 39 40FirstLastNameField* FirstLastNameField::Parse1( 41 std::vector<AutoFillField*>::const_iterator* iter) { 42 // Some pages (e.g. Overstock_comBilling.html, SmithsonianCheckout.html) 43 // have the label "Name" followed by two or three text fields. 44 scoped_ptr<FirstLastNameField> v(new FirstLastNameField); 45 std::vector<AutoFillField*>::const_iterator q = *iter; 46 47 AutoFillField* next; 48 if (ParseText(&q, ASCIIToUTF16("^name"), &v->first_name_) && 49 ParseEmptyText(&q, &next)) { 50 if (ParseEmptyText(&q, &v->last_name_)) { 51 // There are three name fields; assume that the middle one is a 52 // middle initial (it is, at least, on SmithsonianCheckout.html). 53 v->middle_name_ = next; 54 v->middle_initial_ = true; 55 } else { // only two name fields 56 v->last_name_ = next; 57 } 58 59 *iter = q; 60 return v.release(); 61 } 62 63 return NULL; 64} 65 66FirstLastNameField* FirstLastNameField::Parse2( 67 std::vector<AutoFillField*>::const_iterator* iter) { 68 scoped_ptr<FirstLastNameField> v(new FirstLastNameField); 69 std::vector<AutoFillField*>::const_iterator q = *iter; 70 71 // A fair number of pages use the names "fname" and "lname" for naming 72 // first and last name fields (examples from the test suite: 73 // BESTBUY_COM - Sign In2.html; Crate and Barrel Check Out.html; 74 // dell_checkout1.html). At least one UK page (The China Shop2.html) 75 // asks, in stuffy English style, for just initials and a surname, 76 // so we match "initials" here (and just fill in a first name there, 77 // American-style). 78 // The ".*first$" matches fields ending in "first" (example in sample8.html). 79 string16 match = 80 ASCIIToUTF16("first *name|first_name|initials|fname|first$"); 81 if (!ParseText(&q, match, &v->first_name_)) 82 return NULL; 83 84 // We check for a middle initial before checking for a middle name 85 // because at least one page (PC Connection.html) has a field marked 86 // as both (the label text is "MI" and the element name is 87 // "txtmiddlename"); such a field probably actually represents a 88 // middle initial. 89 match = ASCIIToUTF16("middle *initial|middle_initial|m\\.i\\.|mi$"); 90 if (ParseText(&q, match, &v->middle_name_)) { 91 v->middle_initial_ = true; 92 } else { 93 match = ASCIIToUTF16("middle *name|middle_name|mname|middle$"); 94 ParseText(&q, match, &v->middle_name_); 95 } 96 97 // The ".*last$" matches fields ending in "last" (example in sample8.html). 98 match = ASCIIToUTF16("last *name|last_name|lname|surname|last$"); 99 if (!ParseText(&q, match, &v->last_name_)) 100 return NULL; 101 102 *iter = q; 103 return v.release(); 104} 105 106FirstLastNameField* FirstLastNameField::ParseEcmlName( 107 std::vector<AutoFillField*>::const_iterator* iter) { 108 scoped_ptr<FirstLastNameField> field(new FirstLastNameField); 109 std::vector<AutoFillField*>::const_iterator q = *iter; 110 111 string16 pattern = GetEcmlPattern(kEcmlShipToFirstName, 112 kEcmlBillToFirstName, '|'); 113 if (!ParseText(&q, pattern, &field->first_name_)) 114 return NULL; 115 116 pattern = GetEcmlPattern(kEcmlShipToMiddleName, kEcmlBillToMiddleName, '|'); 117 ParseText(&q, pattern, &field->middle_name_); 118 119 pattern = GetEcmlPattern(kEcmlShipToLastName, kEcmlBillToLastName, '|'); 120 if (ParseText(&q, pattern, &field->last_name_)) { 121 *iter = q; 122 return field.release(); 123 } 124 125 return NULL; 126} 127 128FirstLastNameField* FirstLastNameField::Parse( 129 std::vector<AutoFillField*>::const_iterator* iter, 130 bool is_ecml) { 131 if (is_ecml) { 132 return ParseEcmlName(iter); 133 } else { 134 FirstLastNameField* v = Parse1(iter); 135 if (v != NULL) 136 return v; 137 138 return Parse2(iter); 139 } 140} 141 142bool FirstLastNameField::GetFieldInfo(FieldTypeMap* field_type_map) const { 143 bool ok = Add(field_type_map, first_name_, AutoFillType(NAME_FIRST)); 144 DCHECK(ok); 145 ok = ok && Add(field_type_map, last_name_, AutoFillType(NAME_LAST)); 146 DCHECK(ok); 147 AutoFillType type = middle_initial_ ? 148 AutoFillType(NAME_MIDDLE_INITIAL) : AutoFillType(NAME_MIDDLE); 149 ok = ok && Add(field_type_map, middle_name_, type); 150 DCHECK(ok); 151 152 return ok; 153} 154 155FirstLastNameField::FirstLastNameField() 156 : first_name_(NULL), 157 middle_name_(NULL), 158 last_name_(NULL), 159 middle_initial_(false) { 160} 161 162