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_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "components/autofill/core/browser/autofill_type.h"
17 #include "components/autofill/core/common/autofill_l10n_util.h"
23 const char* const name_prefixes
[] = {
24 "1lt", "1st", "2lt", "2nd", "3rd", "admiral", "capt", "captain", "col",
25 "cpt", "dr", "gen", "general", "lcdr", "lt", "ltc", "ltg", "ltjg", "maj",
26 "major", "mg", "mr", "mrs", "ms", "pastor", "prof", "rep", "reverend",
29 const char* const name_suffixes
[] = {
30 "b.a", "ba", "d.d.s", "dds", "i", "ii", "iii", "iv", "ix", "jr", "m.a",
31 "m.d", "ma", "md", "ms", "ph.d", "phd", "sr", "v", "vi", "vii", "viii",
34 const char* const family_name_prefixes
[] = {
35 "d'", "de", "del", "der", "di", "la", "le", "mc", "san", "st", "ter",
38 // Returns true if |set| contains |element|, modulo a final period.
39 bool ContainsString(const char* const set
[],
41 const base::string16
& element
) {
42 if (!base::IsStringASCII(element
))
45 base::string16 trimmed_element
;
46 base::TrimString(element
, base::ASCIIToUTF16("."), &trimmed_element
);
48 for (size_t i
= 0; i
< set_size
; ++i
) {
49 if (base::LowerCaseEqualsASCII(trimmed_element
, set
[i
]))
56 // Removes common name prefixes from |name_tokens|.
57 void StripPrefixes(std::vector
<base::string16
>* name_tokens
) {
58 std::vector
<base::string16
>::iterator iter
= name_tokens
->begin();
59 while(iter
!= name_tokens
->end()) {
60 if (!ContainsString(name_prefixes
, arraysize(name_prefixes
), *iter
))
65 std::vector
<base::string16
> copy_vector
;
66 copy_vector
.assign(iter
, name_tokens
->end());
67 *name_tokens
= copy_vector
;
70 // Removes common name suffixes from |name_tokens|.
71 void StripSuffixes(std::vector
<base::string16
>* name_tokens
) {
72 while(!name_tokens
->empty()) {
73 if (!ContainsString(name_suffixes
, arraysize(name_suffixes
),
74 name_tokens
->back())) {
77 name_tokens
->pop_back();
83 base::string16 middle
;
84 base::string16 family
;
87 // TODO(estade): This does Western name splitting. It should do different
88 // splitting based on the app locale.
89 NameParts
SplitName(const base::string16
& name
) {
90 std::vector
<base::string16
> name_tokens
= base::SplitString(
91 name
, base::ASCIIToUTF16(" ,"), base::KEEP_WHITESPACE
,
92 base::SPLIT_WANT_NONEMPTY
);
93 StripPrefixes(&name_tokens
);
95 // Don't assume "Ma" is a suffix in John Ma.
96 if (name_tokens
.size() > 2)
97 StripSuffixes(&name_tokens
);
101 if (name_tokens
.empty()) {
102 // Bad things have happened; just assume the whole thing is a given name.
107 // Only one token, assume given name.
108 if (name_tokens
.size() == 1) {
109 parts
.given
= name_tokens
[0];
113 // 2 or more tokens. Grab the family, which is the last word plus any
114 // recognizable family prefixes.
115 std::vector
<base::string16
> reverse_family_tokens
;
116 reverse_family_tokens
.push_back(name_tokens
.back());
117 name_tokens
.pop_back();
118 while (name_tokens
.size() >= 1 &&
119 ContainsString(family_name_prefixes
,
120 arraysize(family_name_prefixes
),
121 name_tokens
.back())) {
122 reverse_family_tokens
.push_back(name_tokens
.back());
123 name_tokens
.pop_back();
126 std::vector
<base::string16
> family_tokens(reverse_family_tokens
.rbegin(),
127 reverse_family_tokens
.rend());
128 parts
.family
= base::JoinString(family_tokens
, base::ASCIIToUTF16(" "));
130 // Take the last remaining token as the middle name (if there are at least 2
132 if (name_tokens
.size() >= 2) {
133 parts
.middle
= name_tokens
.back();
134 name_tokens
.pop_back();
137 // Remainder is given name.
138 parts
.given
= base::JoinString(name_tokens
, base::ASCIIToUTF16(" "));
145 NameInfo::NameInfo() {}
147 NameInfo::NameInfo(const NameInfo
& info
) : FormGroup() {
151 NameInfo::~NameInfo() {}
153 NameInfo
& NameInfo::operator=(const NameInfo
& info
) {
157 given_
= info
.given_
;
158 middle_
= info
.middle_
;
159 family_
= info
.family_
;
164 bool NameInfo::ParsedNamesAreEqual(const NameInfo
& info
) const {
165 l10n::CaseInsensitiveCompare compare
;
166 return compare
.StringsEqual(given_
, info
.given_
) &&
167 compare
.StringsEqual(middle_
, info
.middle_
) &&
168 compare
.StringsEqual(family_
, 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 base::JoinString(full_name
, base::ASCIIToUTF16(" "));
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