1 // Copyright 2013 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.
5 #include "components/autofill/core/browser/contact_info.h"
11 #include "base/basictypes.h"
12 #include "base/logging.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "components/autofill/core/browser/autofill_type.h"
21 const char* const name_prefixes
[] = {
22 "1lt", "1st", "2lt", "2nd", "3rd", "admiral", "capt", "captain", "col",
23 "cpt", "dr", "gen", "general", "lcdr", "lt", "ltc", "ltg", "ltjg", "maj",
24 "major", "mg", "mr", "mrs", "ms", "pastor", "prof", "rep", "reverend",
27 const char* const name_suffixes
[] = {
28 "b.a", "ba", "d.d.s", "dds", "i", "ii", "iii", "iv", "ix", "jr", "m.a",
29 "m.d", "ma", "md", "ms", "ph.d", "phd", "sr", "v", "vi", "vii", "viii",
32 const char* const family_name_prefixes
[] = {
33 "d'", "de", "del", "der", "di", "la", "le", "mc", "san", "st", "ter",
36 // Returns true if |set| contains |element|, modulo a final period.
37 bool ContainsString(const char* const set
[],
39 const base::string16
& element
) {
40 if (!base::IsStringASCII(element
))
43 base::string16 trimmed_element
;
44 base::TrimString(element
, base::ASCIIToUTF16("."), &trimmed_element
);
46 for (size_t i
= 0; i
< set_size
; ++i
) {
47 if (LowerCaseEqualsASCII(trimmed_element
, set
[i
]))
54 // Removes common name prefixes from |name_tokens|.
55 void StripPrefixes(std::vector
<base::string16
>* name_tokens
) {
56 std::vector
<base::string16
>::iterator iter
= name_tokens
->begin();
57 while(iter
!= name_tokens
->end()) {
58 if (!ContainsString(name_prefixes
, arraysize(name_prefixes
), *iter
))
63 std::vector
<base::string16
> copy_vector
;
64 copy_vector
.assign(iter
, name_tokens
->end());
65 *name_tokens
= copy_vector
;
68 // Removes common name suffixes from |name_tokens|.
69 void StripSuffixes(std::vector
<base::string16
>* name_tokens
) {
70 while(!name_tokens
->empty()) {
71 if (!ContainsString(name_suffixes
, arraysize(name_suffixes
),
72 name_tokens
->back())) {
75 name_tokens
->pop_back();
81 base::string16 middle
;
82 base::string16 family
;
85 // TODO(estade): This does Western name splitting. It should do different
86 // splitting based on the app locale.
87 NameParts
SplitName(const base::string16
& name
) {
88 std::vector
<base::string16
> name_tokens
;
89 Tokenize(name
, base::ASCIIToUTF16(" ,"), &name_tokens
);
91 StripPrefixes(&name_tokens
);
93 // Don't assume "Ma" is a suffix in John Ma.
94 if (name_tokens
.size() > 2)
95 StripSuffixes(&name_tokens
);
99 if (name_tokens
.empty()) {
100 // Bad things have happened; just assume the whole thing is a given name.
105 // Only one token, assume given name.
106 if (name_tokens
.size() == 1) {
107 parts
.given
= name_tokens
[0];
111 // 2 or more tokens. Grab the family, which is the last word plus any
112 // recognizable family prefixes.
113 std::vector
<base::string16
> reverse_family_tokens
;
114 reverse_family_tokens
.push_back(name_tokens
.back());
115 name_tokens
.pop_back();
116 while (name_tokens
.size() >= 1 &&
117 ContainsString(family_name_prefixes
,
118 arraysize(family_name_prefixes
),
119 name_tokens
.back())) {
120 reverse_family_tokens
.push_back(name_tokens
.back());
121 name_tokens
.pop_back();
124 std::vector
<base::string16
> family_tokens(reverse_family_tokens
.rbegin(),
125 reverse_family_tokens
.rend());
126 parts
.family
= JoinString(family_tokens
, base::char16(' '));
128 // Take the last remaining token as the middle name (if there are at least 2
130 if (name_tokens
.size() >= 2) {
131 parts
.middle
= name_tokens
.back();
132 name_tokens
.pop_back();
135 // Remainder is given name.
136 parts
.given
= JoinString(name_tokens
, base::char16(' '));
143 NameInfo::NameInfo() {}
145 NameInfo::NameInfo(const NameInfo
& info
) : FormGroup() {
149 NameInfo::~NameInfo() {}
151 NameInfo
& NameInfo::operator=(const NameInfo
& info
) {
155 given_
= info
.given_
;
156 middle_
= info
.middle_
;
157 family_
= info
.family_
;
162 bool NameInfo::ParsedNamesAreEqual(const NameInfo
& info
) {
163 return (base::StringToLowerASCII(given_
) ==
164 base::StringToLowerASCII(info
.given_
) &&
165 base::StringToLowerASCII(middle_
) ==
166 base::StringToLowerASCII(info
.middle_
) &&
167 base::StringToLowerASCII(family_
) ==
168 base::StringToLowerASCII(info
.family_
));
171 void NameInfo::GetSupportedTypes(ServerFieldTypeSet
* supported_types
) const {
172 supported_types
->insert(NAME_FIRST
);
173 supported_types
->insert(NAME_MIDDLE
);
174 supported_types
->insert(NAME_LAST
);
175 supported_types
->insert(NAME_MIDDLE_INITIAL
);
176 supported_types
->insert(NAME_FULL
);
179 base::string16
NameInfo::GetRawInfo(ServerFieldType type
) const {
180 DCHECK_EQ(NAME
, AutofillType(type
).group());
191 case NAME_MIDDLE_INITIAL
:
192 return MiddleInitial();
198 return base::string16();
202 void NameInfo::SetRawInfo(ServerFieldType type
, const base::string16
& value
) {
203 DCHECK_EQ(NAME
, AutofillType(type
).group());
211 case NAME_MIDDLE_INITIAL
:
228 base::string16
NameInfo::GetInfo(const AutofillType
& type
,
229 const std::string
& app_locale
) const {
230 if (type
.GetStorableType() == NAME_FULL
)
233 return GetRawInfo(type
.GetStorableType());
236 bool NameInfo::SetInfo(const AutofillType
& type
,
237 const base::string16
& value
,
238 const std::string
& app_locale
) {
239 // Always clear out the full name if we're making a change.
240 if (value
!= GetInfo(type
, app_locale
))
243 if (type
.GetStorableType() == NAME_FULL
) {
248 return FormGroup::SetInfo(type
, value
, app_locale
);
251 base::string16
NameInfo::FullName() const {
255 std::vector
<base::string16
> full_name
;
257 full_name
.push_back(given_
);
259 if (!middle_
.empty())
260 full_name
.push_back(middle_
);
262 if (!family_
.empty())
263 full_name
.push_back(family_
);
265 return JoinString(full_name
, ' ');
268 base::string16
NameInfo::MiddleInitial() const {
270 return base::string16();
272 base::string16
middle_name(middle_
);
273 base::string16 initial
;
274 initial
.push_back(middle_name
[0]);
278 void NameInfo::SetFullName(const base::string16
& full
) {
281 // If |full| is empty, leave the other name parts alone. This might occur
282 // due to a migrated database with an empty |full_name| value.
286 NameParts parts
= SplitName(full
);
287 given_
= parts
.given
;
288 middle_
= parts
.middle
;
289 family_
= parts
.family
;
292 EmailInfo::EmailInfo() {}
294 EmailInfo::EmailInfo(const EmailInfo
& info
) : FormGroup() {
298 EmailInfo::~EmailInfo() {}
300 EmailInfo
& EmailInfo::operator=(const EmailInfo
& info
) {
304 email_
= info
.email_
;
308 void EmailInfo::GetSupportedTypes(ServerFieldTypeSet
* supported_types
) const {
309 supported_types
->insert(EMAIL_ADDRESS
);
312 base::string16
EmailInfo::GetRawInfo(ServerFieldType type
) const {
313 if (type
== EMAIL_ADDRESS
)
316 return base::string16();
319 void EmailInfo::SetRawInfo(ServerFieldType type
, const base::string16
& value
) {
320 DCHECK_EQ(EMAIL_ADDRESS
, type
);
324 CompanyInfo::CompanyInfo() {}
326 CompanyInfo::CompanyInfo(const CompanyInfo
& info
) : FormGroup() {
330 CompanyInfo::~CompanyInfo() {}
332 CompanyInfo
& CompanyInfo::operator=(const CompanyInfo
& info
) {
336 company_name_
= info
.company_name_
;
340 void CompanyInfo::GetSupportedTypes(ServerFieldTypeSet
* supported_types
) const {
341 supported_types
->insert(COMPANY_NAME
);
344 base::string16
CompanyInfo::GetRawInfo(ServerFieldType type
) const {
345 if (type
== COMPANY_NAME
)
346 return company_name_
;
348 return base::string16();
351 void CompanyInfo::SetRawInfo(ServerFieldType type
,
352 const base::string16
& value
) {
353 DCHECK_EQ(COMPANY_NAME
, type
);
354 company_name_
= value
;
357 } // namespace autofill