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