blob: 6e18011e5c439f5a43bd53c1bf9154879f183fa4 [file] [log] [blame]
Ben Murdocheb525c52013-07-10 11:40:50 +01001// 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.
4
5#include "components/autofill/core/browser/autofill_profile.h"
6
7#include <algorithm>
8#include <functional>
9#include <map>
10#include <ostream>
11#include <set>
12
13#include "base/basictypes.h"
14#include "base/guid.h"
15#include "base/logging.h"
16#include "base/strings/string_util.h"
17#include "base/strings/utf_string_conversions.h"
18#include "components/autofill/core/browser/address.h"
19#include "components/autofill/core/browser/autofill_country.h"
20#include "components/autofill/core/browser/autofill_field.h"
21#include "components/autofill/core/browser/autofill_type.h"
22#include "components/autofill/core/browser/contact_info.h"
23#include "components/autofill/core/browser/phone_number.h"
24#include "components/autofill/core/browser/phone_number_i18n.h"
25#include "components/autofill/core/browser/validation.h"
26#include "components/autofill/core/common/form_field_data.h"
27#include "grit/component_strings.h"
28#include "ui/base/l10n/l10n_util.h"
29
30namespace autofill {
31namespace {
32
Ben Murdochbb1529c2013-08-08 10:24:53 +010033// Like |AutofillType::GetStorableType()|, but also returns |NAME_FULL| for
34// first, middle, and last name field types.
35ServerFieldType GetStorableTypeCollapsingNames(ServerFieldType type) {
36 ServerFieldType storable_type = AutofillType(type).GetStorableType();
37 if (AutofillType(storable_type).group() == NAME)
Ben Murdocheb525c52013-07-10 11:40:50 +010038 return NAME_FULL;
39
Ben Murdochbb1529c2013-08-08 10:24:53 +010040 return storable_type;
Ben Murdocheb525c52013-07-10 11:40:50 +010041}
42
43// Fills |distinguishing_fields| with a list of fields to use when creating
44// labels that can help to distinguish between two profiles. Draws fields from
45// |suggested_fields| if it is non-NULL; otherwise returns a default list.
46// If |suggested_fields| is non-NULL, does not include |excluded_field| in the
47// list. Otherwise, |excluded_field| is ignored, and should be set to
48// |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in
49// decreasing order of importance.
50void GetFieldsForDistinguishingProfiles(
Ben Murdoch32409262013-08-07 11:04:47 +010051 const std::vector<ServerFieldType>* suggested_fields,
52 ServerFieldType excluded_field,
53 std::vector<ServerFieldType>* distinguishing_fields) {
54 static const ServerFieldType kDefaultDistinguishingFields[] = {
Ben Murdocheb525c52013-07-10 11:40:50 +010055 NAME_FULL,
56 ADDRESS_HOME_LINE1,
57 ADDRESS_HOME_LINE2,
58 ADDRESS_HOME_CITY,
59 ADDRESS_HOME_STATE,
60 ADDRESS_HOME_ZIP,
61 ADDRESS_HOME_COUNTRY,
62 EMAIL_ADDRESS,
63 PHONE_HOME_WHOLE_NUMBER,
64 COMPANY_NAME,
65 };
66
67 if (!suggested_fields) {
68 DCHECK_EQ(excluded_field, UNKNOWN_TYPE);
69 distinguishing_fields->assign(
70 kDefaultDistinguishingFields,
71 kDefaultDistinguishingFields + arraysize(kDefaultDistinguishingFields));
72 return;
73 }
74
75 // Keep track of which fields we've seen so that we avoid duplicate entries.
76 // Always ignore fields of unknown type and the excluded field.
Ben Murdoch32409262013-08-07 11:04:47 +010077 std::set<ServerFieldType> seen_fields;
Ben Murdocheb525c52013-07-10 11:40:50 +010078 seen_fields.insert(UNKNOWN_TYPE);
Ben Murdochbb1529c2013-08-08 10:24:53 +010079 seen_fields.insert(GetStorableTypeCollapsingNames(excluded_field));
Ben Murdocheb525c52013-07-10 11:40:50 +010080
81 distinguishing_fields->clear();
Ben Murdoch32409262013-08-07 11:04:47 +010082 for (std::vector<ServerFieldType>::const_iterator it =
Ben Murdocheb525c52013-07-10 11:40:50 +010083 suggested_fields->begin();
84 it != suggested_fields->end(); ++it) {
Ben Murdochbb1529c2013-08-08 10:24:53 +010085 ServerFieldType suggested_type = GetStorableTypeCollapsingNames(*it);
Ben Murdocheb525c52013-07-10 11:40:50 +010086 if (seen_fields.insert(suggested_type).second)
87 distinguishing_fields->push_back(suggested_type);
88 }
89
90 // Special case: If the excluded field is a partial name (e.g. first name) and
91 // the suggested fields include other name fields, include |NAME_FULL| in the
92 // list of distinguishing fields as a last-ditch fallback. This allows us to
93 // distinguish between profiles that are identical except for the name.
94 if (excluded_field != NAME_FULL &&
Ben Murdochbb1529c2013-08-08 10:24:53 +010095 GetStorableTypeCollapsingNames(excluded_field) == NAME_FULL) {
Ben Murdoch32409262013-08-07 11:04:47 +010096 for (std::vector<ServerFieldType>::const_iterator it =
Ben Murdocheb525c52013-07-10 11:40:50 +010097 suggested_fields->begin();
98 it != suggested_fields->end(); ++it) {
99 if (*it != excluded_field &&
Ben Murdochbb1529c2013-08-08 10:24:53 +0100100 GetStorableTypeCollapsingNames(*it) == NAME_FULL) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100101 distinguishing_fields->push_back(NAME_FULL);
102 break;
103 }
104 }
105 }
106}
107
108// A helper function for string streaming. Concatenates multi-valued entries
109// stored for a given |type| into a single string. This string is returned.
110const base::string16 MultiString(const AutofillProfile& p,
Ben Murdoch32409262013-08-07 11:04:47 +0100111 ServerFieldType type) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100112 std::vector<base::string16> values;
113 p.GetRawMultiInfo(type, &values);
114 base::string16 accumulate;
115 for (size_t i = 0; i < values.size(); ++i) {
116 if (i > 0)
117 accumulate += ASCIIToUTF16(" ");
118 accumulate += values[i];
119 }
120 return accumulate;
121}
122
123base::string16 GetFormGroupInfo(const FormGroup& form_group,
Ben Murdoch32409262013-08-07 11:04:47 +0100124 const AutofillType& type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100125 const std::string& app_locale) {
126 return app_locale.empty() ?
Ben Murdochbb1529c2013-08-08 10:24:53 +0100127 form_group.GetRawInfo(type.GetStorableType()) :
Ben Murdocheb525c52013-07-10 11:40:50 +0100128 form_group.GetInfo(type, app_locale);
129}
130
131template <class T>
Ben Murdoch32409262013-08-07 11:04:47 +0100132void CopyValuesToItems(ServerFieldType type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100133 const std::vector<base::string16>& values,
134 std::vector<T>* form_group_items,
135 const T& prototype) {
136 form_group_items->resize(values.size(), prototype);
137 for (size_t i = 0; i < form_group_items->size(); ++i) {
138 (*form_group_items)[i].SetRawInfo(type,
139 CollapseWhitespace(values[i], false));
140 }
141 // Must have at least one (possibly empty) element.
142 if (form_group_items->empty())
143 form_group_items->resize(1, prototype);
144}
145
146template <class T>
Ben Murdoch32409262013-08-07 11:04:47 +0100147void CopyItemsToValues(const AutofillType& type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100148 const std::vector<T>& form_group_items,
149 const std::string& app_locale,
150 std::vector<base::string16>* values) {
151 values->resize(form_group_items.size());
152 for (size_t i = 0; i < values->size(); ++i) {
153 (*values)[i] = GetFormGroupInfo(form_group_items[i], type, app_locale);
154 }
155}
156
157// Collapse compound field types to their "full" type. I.e. First name
158// collapses to full name, area code collapses to full phone, etc.
Ben Murdoch32409262013-08-07 11:04:47 +0100159void CollapseCompoundFieldTypes(ServerFieldTypeSet* type_set) {
160 ServerFieldTypeSet collapsed_set;
161 for (ServerFieldTypeSet::iterator it = type_set->begin();
162 it != type_set->end(); ++it) {
163 switch (*it) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100164 case NAME_FIRST:
165 case NAME_MIDDLE:
166 case NAME_LAST:
167 case NAME_MIDDLE_INITIAL:
168 case NAME_FULL:
169 case NAME_SUFFIX:
170 collapsed_set.insert(NAME_FULL);
171 break;
172
173 case PHONE_HOME_NUMBER:
174 case PHONE_HOME_CITY_CODE:
175 case PHONE_HOME_COUNTRY_CODE:
176 case PHONE_HOME_CITY_AND_NUMBER:
177 case PHONE_HOME_WHOLE_NUMBER:
178 collapsed_set.insert(PHONE_HOME_WHOLE_NUMBER);
179 break;
180
181 default:
Ben Murdoch32409262013-08-07 11:04:47 +0100182 collapsed_set.insert(*it);
Ben Murdocheb525c52013-07-10 11:40:50 +0100183 }
184 }
185 std::swap(*type_set, collapsed_set);
186}
187
188class FindByPhone {
189 public:
190 FindByPhone(const base::string16& phone,
191 const std::string& country_code,
192 const std::string& app_locale)
193 : phone_(phone),
194 country_code_(country_code),
195 app_locale_(app_locale) {
196 }
197
198 bool operator()(const base::string16& phone) {
199 return i18n::PhoneNumbersMatch(phone, phone_, country_code_, app_locale_);
200 }
201
202 bool operator()(const base::string16* phone) {
203 return i18n::PhoneNumbersMatch(*phone, phone_, country_code_, app_locale_);
204 }
205
206 private:
207 base::string16 phone_;
208 std::string country_code_;
209 std::string app_locale_;
210};
211
212// Functor used to check for case-insensitive equality of two strings.
213struct CaseInsensitiveStringEquals
214 : public std::binary_function<base::string16, base::string16, bool>
215{
216 bool operator()(const base::string16& x, const base::string16& y) const {
217 return
218 x.size() == y.size() && StringToLowerASCII(x) == StringToLowerASCII(y);
219 }
220};
221
222} // namespace
223
224AutofillProfile::AutofillProfile(const std::string& guid,
225 const std::string& origin)
226 : AutofillDataModel(guid, origin),
227 name_(1),
228 email_(1),
229 phone_number_(1, PhoneNumber(this)) {
230}
231
232AutofillProfile::AutofillProfile()
233 : AutofillDataModel(base::GenerateGUID(), std::string()),
234 name_(1),
235 email_(1),
236 phone_number_(1, PhoneNumber(this)) {
237}
238
239AutofillProfile::AutofillProfile(const AutofillProfile& profile)
240 : AutofillDataModel(std::string(), std::string()) {
241 operator=(profile);
242}
243
244AutofillProfile::~AutofillProfile() {
245}
246
247AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
248 if (this == &profile)
249 return *this;
250
251 set_guid(profile.guid());
252 set_origin(profile.origin());
253
254 label_ = profile.label_;
255 name_ = profile.name_;
256 email_ = profile.email_;
257 company_ = profile.company_;
258 phone_number_ = profile.phone_number_;
259
260 for (size_t i = 0; i < phone_number_.size(); ++i)
261 phone_number_[i].set_profile(this);
262
263 address_ = profile.address_;
264
265 return *this;
266}
267
Ben Murdoch32409262013-08-07 11:04:47 +0100268void AutofillProfile::GetMatchingTypes(
269 const base::string16& text,
270 const std::string& app_locale,
271 ServerFieldTypeSet* matching_types) const {
Ben Murdocheb525c52013-07-10 11:40:50 +0100272 FormGroupList info = FormGroups();
273 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
274 (*it)->GetMatchingTypes(text, app_locale, matching_types);
275}
276
Ben Murdoch32409262013-08-07 11:04:47 +0100277base::string16 AutofillProfile::GetRawInfo(ServerFieldType type) const {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100278 const FormGroup* form_group = FormGroupForType(AutofillType(type));
Ben Murdocheb525c52013-07-10 11:40:50 +0100279 if (!form_group)
280 return base::string16();
281
Ben Murdochbb1529c2013-08-08 10:24:53 +0100282 return form_group->GetRawInfo(type);
Ben Murdocheb525c52013-07-10 11:40:50 +0100283}
284
Ben Murdoch32409262013-08-07 11:04:47 +0100285void AutofillProfile::SetRawInfo(ServerFieldType type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100286 const base::string16& value) {
Ben Murdoch32409262013-08-07 11:04:47 +0100287 FormGroup* form_group = MutableFormGroupForType(AutofillType(type));
Ben Murdocheb525c52013-07-10 11:40:50 +0100288 if (form_group)
289 form_group->SetRawInfo(type, CollapseWhitespace(value, false));
290}
291
Ben Murdoch32409262013-08-07 11:04:47 +0100292base::string16 AutofillProfile::GetInfo(const AutofillType& type,
293 const std::string& app_locale) const {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100294 const FormGroup* form_group = FormGroupForType(type);
Ben Murdocheb525c52013-07-10 11:40:50 +0100295 if (!form_group)
296 return base::string16();
297
Ben Murdochbb1529c2013-08-08 10:24:53 +0100298 return form_group->GetInfo(type, app_locale);
Ben Murdocheb525c52013-07-10 11:40:50 +0100299}
300
Ben Murdoch32409262013-08-07 11:04:47 +0100301bool AutofillProfile::SetInfo(const AutofillType& type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100302 const base::string16& value,
303 const std::string& app_locale) {
304 FormGroup* form_group = MutableFormGroupForType(type);
305 if (!form_group)
306 return false;
307
308 return
309 form_group->SetInfo(type, CollapseWhitespace(value, false), app_locale);
310}
311
312void AutofillProfile::SetRawMultiInfo(
Ben Murdoch32409262013-08-07 11:04:47 +0100313 ServerFieldType type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100314 const std::vector<base::string16>& values) {
315 switch (AutofillType(type).group()) {
Ben Murdoch2385ea32013-08-06 11:01:04 +0100316 case NAME:
317 case NAME_BILLING:
Ben Murdocheb525c52013-07-10 11:40:50 +0100318 CopyValuesToItems(type, values, &name_, NameInfo());
319 break;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100320 case EMAIL:
Ben Murdocheb525c52013-07-10 11:40:50 +0100321 CopyValuesToItems(type, values, &email_, EmailInfo());
322 break;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100323 case PHONE_HOME:
324 case PHONE_BILLING:
Ben Murdocheb525c52013-07-10 11:40:50 +0100325 CopyValuesToItems(type,
326 values,
327 &phone_number_,
328 PhoneNumber(this));
329 break;
330 default:
331 if (values.size() == 1) {
332 SetRawInfo(type, values[0]);
333 } else if (values.size() == 0) {
334 SetRawInfo(type, base::string16());
335 } else {
336 // Shouldn't attempt to set multiple values on single-valued field.
337 NOTREACHED();
338 }
339 break;
340 }
341}
342
343void AutofillProfile::GetRawMultiInfo(
Ben Murdoch32409262013-08-07 11:04:47 +0100344 ServerFieldType type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100345 std::vector<base::string16>* values) const {
Ben Murdoch32409262013-08-07 11:04:47 +0100346 GetMultiInfoImpl(AutofillType(type), std::string(), values);
Ben Murdocheb525c52013-07-10 11:40:50 +0100347}
348
Ben Murdoch32409262013-08-07 11:04:47 +0100349void AutofillProfile::GetMultiInfo(const AutofillType& type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100350 const std::string& app_locale,
351 std::vector<base::string16>* values) const {
352 GetMultiInfoImpl(type, app_locale, values);
353}
354
355void AutofillProfile::FillFormField(const AutofillField& field,
356 size_t variant,
357 const std::string& app_locale,
358 FormFieldData* field_data) const {
Ben Murdoch32409262013-08-07 11:04:47 +0100359 AutofillType type = field.Type();
360 DCHECK_NE(CREDIT_CARD, type.group());
Ben Murdocheb525c52013-07-10 11:40:50 +0100361 DCHECK(field_data);
362
Ben Murdochbb1529c2013-08-08 10:24:53 +0100363 if (type.GetStorableType() == PHONE_HOME_NUMBER) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100364 FillPhoneNumberField(field, variant, app_locale, field_data);
365 } else if (field_data->form_control_type == "select-one") {
366 FillSelectControl(type, app_locale, field_data);
367 } else {
368 std::vector<base::string16> values;
369 GetMultiInfo(type, app_locale, &values);
370 if (variant >= values.size()) {
371 // If the variant is unavailable, bail. This case is reachable, for
372 // example if Sync updates a profile during the filling process.
373 return;
374 }
375
376 field_data->value = values[variant];
377 }
378}
379
380void AutofillProfile::FillPhoneNumberField(const AutofillField& field,
381 size_t variant,
382 const std::string& app_locale,
383 FormFieldData* field_data) const {
384 std::vector<base::string16> values;
Ben Murdoch32409262013-08-07 11:04:47 +0100385 GetMultiInfo(field.Type(), app_locale, &values);
Ben Murdocheb525c52013-07-10 11:40:50 +0100386 DCHECK(variant < values.size());
387
388 // If we are filling a phone number, check to see if the size field
389 // matches the "prefix" or "suffix" sizes and fill accordingly.
390 base::string16 number = values[variant];
391 if (number.length() ==
392 PhoneNumber::kPrefixLength + PhoneNumber::kSuffixLength) {
393 if (field.phone_part() == AutofillField::PHONE_PREFIX ||
394 field_data->max_length == PhoneNumber::kPrefixLength) {
395 number = number.substr(PhoneNumber::kPrefixOffset,
396 PhoneNumber::kPrefixLength);
397 } else if (field.phone_part() == AutofillField::PHONE_SUFFIX ||
398 field_data->max_length == PhoneNumber::kSuffixLength) {
399 number = number.substr(PhoneNumber::kSuffixOffset,
400 PhoneNumber::kSuffixLength);
401 }
402 }
403
404 field_data->value = number;
405}
406
407const base::string16 AutofillProfile::Label() const {
408 return label_;
409}
410
411bool AutofillProfile::IsEmpty(const std::string& app_locale) const {
Ben Murdoch32409262013-08-07 11:04:47 +0100412 ServerFieldTypeSet types;
Ben Murdocheb525c52013-07-10 11:40:50 +0100413 GetNonEmptyTypes(app_locale, &types);
414 return types.empty();
415}
416
Ben Murdoch32409262013-08-07 11:04:47 +0100417bool AutofillProfile::IsPresentButInvalid(ServerFieldType type) const {
Ben Murdocheb525c52013-07-10 11:40:50 +0100418 std::string country = UTF16ToUTF8(GetRawInfo(ADDRESS_HOME_COUNTRY));
419 base::string16 data = GetRawInfo(type);
420 switch (type) {
421 case ADDRESS_HOME_STATE:
422 if (!data.empty() && country == "US" && !autofill::IsValidState(data))
423 return true;
424 break;
425
426 case ADDRESS_HOME_ZIP:
427 if (!data.empty() && country == "US" && !autofill::IsValidZip(data))
428 return true;
429 break;
430
431 case PHONE_HOME_WHOLE_NUMBER: {
432 if (!data.empty() && !i18n::PhoneObject(data, country).IsValidNumber())
433 return true;
434 break;
435 }
436
437 default:
438 NOTREACHED();
439 break;
440 }
441
442 return false;
443}
444
445
446int AutofillProfile::Compare(const AutofillProfile& profile) const {
Ben Murdoch32409262013-08-07 11:04:47 +0100447 const ServerFieldType single_value_types[] = { COMPANY_NAME,
448 ADDRESS_HOME_LINE1,
449 ADDRESS_HOME_LINE2,
450 ADDRESS_HOME_CITY,
451 ADDRESS_HOME_STATE,
452 ADDRESS_HOME_ZIP,
453 ADDRESS_HOME_COUNTRY };
Ben Murdocheb525c52013-07-10 11:40:50 +0100454
455 for (size_t i = 0; i < arraysize(single_value_types); ++i) {
456 int comparison = GetRawInfo(single_value_types[i]).compare(
457 profile.GetRawInfo(single_value_types[i]));
458 if (comparison != 0)
459 return comparison;
460 }
461
Ben Murdoch32409262013-08-07 11:04:47 +0100462 const ServerFieldType multi_value_types[] = { NAME_FIRST,
463 NAME_MIDDLE,
464 NAME_LAST,
465 EMAIL_ADDRESS,
466 PHONE_HOME_WHOLE_NUMBER };
Ben Murdocheb525c52013-07-10 11:40:50 +0100467
468 for (size_t i = 0; i < arraysize(multi_value_types); ++i) {
469 std::vector<base::string16> values_a;
470 std::vector<base::string16> values_b;
471 GetRawMultiInfo(multi_value_types[i], &values_a);
472 profile.GetRawMultiInfo(multi_value_types[i], &values_b);
473 if (values_a.size() < values_b.size())
474 return -1;
475 if (values_a.size() > values_b.size())
476 return 1;
477 for (size_t j = 0; j < values_a.size(); ++j) {
478 int comparison = values_a[j].compare(values_b[j]);
479 if (comparison != 0)
480 return comparison;
481 }
482 }
483
484 return 0;
485}
486
487bool AutofillProfile::operator==(const AutofillProfile& profile) const {
488 return guid() == profile.guid() &&
489 origin() == profile.origin() &&
490 Compare(profile) == 0;
491}
492
493bool AutofillProfile::operator!=(const AutofillProfile& profile) const {
494 return !operator==(profile);
495}
496
497const base::string16 AutofillProfile::PrimaryValue() const {
498 return GetRawInfo(ADDRESS_HOME_LINE1) + GetRawInfo(ADDRESS_HOME_CITY);
499}
500
501bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile,
502 const std::string& app_locale) const {
Ben Murdoch32409262013-08-07 11:04:47 +0100503 ServerFieldTypeSet types;
Ben Murdocheb525c52013-07-10 11:40:50 +0100504 GetNonEmptyTypes(app_locale, &types);
505
Ben Murdoch32409262013-08-07 11:04:47 +0100506 for (ServerFieldTypeSet::const_iterator it = types.begin(); it != types.end();
507 ++it) {
508 if (*it == NAME_FULL) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100509 // Ignore the compound "full name" field type. We are only interested in
510 // comparing the constituent parts. For example, if |this| has a middle
511 // name saved, but |profile| lacks one, |profile| could still be a subset
512 // of |this|.
513 continue;
Ben Murdoch32409262013-08-07 11:04:47 +0100514 } else if (AutofillType(*it).group() == PHONE_HOME) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100515 // Phone numbers should be canonicalized prior to being compared.
Ben Murdoch32409262013-08-07 11:04:47 +0100516 if (*it != PHONE_HOME_WHOLE_NUMBER) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100517 continue;
518 } else if (!i18n::PhoneNumbersMatch(
Ben Murdoch32409262013-08-07 11:04:47 +0100519 GetRawInfo(*it),
520 profile.GetRawInfo(*it),
Ben Murdocheb525c52013-07-10 11:40:50 +0100521 UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)),
522 app_locale)) {
523 return false;
524 }
Ben Murdoch32409262013-08-07 11:04:47 +0100525 } else if (StringToLowerASCII(GetRawInfo(*it)) !=
526 StringToLowerASCII(profile.GetRawInfo(*it))) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100527 return false;
528 }
529 }
530
531 return true;
532}
533
534void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile,
535 const std::string& app_locale) {
536 // Verified profiles should never be overwritten with unverified data.
537 DCHECK(!IsVerified() || profile.IsVerified());
538 set_origin(profile.origin());
539
Ben Murdoch32409262013-08-07 11:04:47 +0100540 ServerFieldTypeSet field_types;
Ben Murdocheb525c52013-07-10 11:40:50 +0100541 profile.GetNonEmptyTypes(app_locale, &field_types);
542
543 // Only transfer "full" types (e.g. full name) and not fragments (e.g.
544 // first name, last name).
545 CollapseCompoundFieldTypes(&field_types);
546
Ben Murdoch32409262013-08-07 11:04:47 +0100547 for (ServerFieldTypeSet::const_iterator iter = field_types.begin();
Ben Murdocheb525c52013-07-10 11:40:50 +0100548 iter != field_types.end(); ++iter) {
549 if (AutofillProfile::SupportsMultiValue(*iter)) {
550 std::vector<base::string16> new_values;
551 profile.GetRawMultiInfo(*iter, &new_values);
552 std::vector<base::string16> existing_values;
553 GetRawMultiInfo(*iter, &existing_values);
554
555 // GetMultiInfo always returns at least one element, even if the profile
556 // has no data stored for this field type.
557 if (existing_values.size() == 1 && existing_values.front().empty())
558 existing_values.clear();
559
560 FieldTypeGroup group = AutofillType(*iter).group();
561 for (std::vector<base::string16>::iterator value_iter =
562 new_values.begin();
563 value_iter != new_values.end(); ++value_iter) {
564 // Don't add duplicates.
Ben Murdoch2385ea32013-08-06 11:01:04 +0100565 if (group == PHONE_HOME) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100566 AddPhoneIfUnique(*value_iter, app_locale, &existing_values);
567 } else {
568 std::vector<base::string16>::const_iterator existing_iter =
569 std::find_if(
570 existing_values.begin(), existing_values.end(),
571 std::bind1st(CaseInsensitiveStringEquals(), *value_iter));
572 if (existing_iter == existing_values.end())
573 existing_values.insert(existing_values.end(), *value_iter);
574 }
575 }
576 SetRawMultiInfo(*iter, existing_values);
577 } else {
578 base::string16 new_value = profile.GetRawInfo(*iter);
579 if (StringToLowerASCII(GetRawInfo(*iter)) !=
580 StringToLowerASCII(new_value)) {
581 SetRawInfo(*iter, new_value);
582 }
583 }
584 }
585}
586
587// static
Ben Murdoch32409262013-08-07 11:04:47 +0100588bool AutofillProfile::SupportsMultiValue(ServerFieldType type) {
Ben Murdoch2385ea32013-08-06 11:01:04 +0100589 FieldTypeGroup group = AutofillType(type).group();
590 return group == NAME ||
591 group == NAME_BILLING ||
592 group == EMAIL ||
593 group == PHONE_HOME ||
594 group == PHONE_BILLING;
Ben Murdocheb525c52013-07-10 11:40:50 +0100595}
596
597// static
598bool AutofillProfile::AdjustInferredLabels(
599 std::vector<AutofillProfile*>* profiles) {
600 const size_t kMinimalFieldsShown = 2;
601
602 std::vector<base::string16> created_labels;
603 CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown,
604 &created_labels);
605 DCHECK_EQ(profiles->size(), created_labels.size());
606
607 bool updated_labels = false;
608 for (size_t i = 0; i < profiles->size(); ++i) {
609 if ((*profiles)[i]->Label() != created_labels[i]) {
610 updated_labels = true;
611 (*profiles)[i]->label_ = created_labels[i];
612 }
613 }
614 return updated_labels;
615}
616
617// static
618void AutofillProfile::CreateInferredLabels(
619 const std::vector<AutofillProfile*>* profiles,
Ben Murdoch32409262013-08-07 11:04:47 +0100620 const std::vector<ServerFieldType>* suggested_fields,
621 ServerFieldType excluded_field,
Ben Murdocheb525c52013-07-10 11:40:50 +0100622 size_t minimal_fields_shown,
623 std::vector<base::string16>* created_labels) {
624 DCHECK(profiles);
625 DCHECK(created_labels);
626
Ben Murdoch32409262013-08-07 11:04:47 +0100627 std::vector<ServerFieldType> fields_to_use;
Ben Murdocheb525c52013-07-10 11:40:50 +0100628 GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field,
629 &fields_to_use);
630
631 // Construct the default label for each profile. Also construct a map that
632 // associates each label with the profiles that have this label. This map is
633 // then used to detect which labels need further differentiating fields.
634 std::map<base::string16, std::list<size_t> > labels;
635 for (size_t i = 0; i < profiles->size(); ++i) {
636 base::string16 label =
637 (*profiles)[i]->ConstructInferredLabel(fields_to_use,
638 minimal_fields_shown);
639 labels[label].push_back(i);
640 }
641
642 created_labels->resize(profiles->size());
643 for (std::map<base::string16, std::list<size_t> >::const_iterator it =
644 labels.begin();
645 it != labels.end(); ++it) {
646 if (it->second.size() == 1) {
647 // This label is unique, so use it without any further ado.
648 base::string16 label = it->first;
649 size_t profile_index = it->second.front();
650 (*created_labels)[profile_index] = label;
651 } else {
652 // We have more than one profile with the same label, so add
653 // differentiating fields.
654 CreateDifferentiatingLabels(*profiles, it->second, fields_to_use,
655 minimal_fields_shown, created_labels);
656 }
657 }
658}
659
Ben Murdoch32409262013-08-07 11:04:47 +0100660void AutofillProfile::GetSupportedTypes(
661 ServerFieldTypeSet* supported_types) const {
Ben Murdocheb525c52013-07-10 11:40:50 +0100662 FormGroupList info = FormGroups();
663 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
664 (*it)->GetSupportedTypes(supported_types);
665}
666
667bool AutofillProfile::FillCountrySelectControl(
668 const std::string& app_locale,
669 FormFieldData* field_data) const {
670 std::string country_code = UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY));
671
672 DCHECK_EQ(field_data->option_values.size(),
673 field_data->option_contents.size());
674 for (size_t i = 0; i < field_data->option_values.size(); ++i) {
675 // Canonicalize each <option> value to a country code, and compare to the
676 // target country code.
677 base::string16 value = field_data->option_values[i];
678 base::string16 contents = field_data->option_contents[i];
679 if (country_code == AutofillCountry::GetCountryCode(value, app_locale) ||
680 country_code == AutofillCountry::GetCountryCode(contents, app_locale)) {
681 field_data->value = value;
682 return true;
683 }
684 }
685
686 return false;
687}
688
689void AutofillProfile::GetMultiInfoImpl(
Ben Murdoch32409262013-08-07 11:04:47 +0100690 const AutofillType& type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100691 const std::string& app_locale,
692 std::vector<base::string16>* values) const {
Ben Murdoch32409262013-08-07 11:04:47 +0100693 switch (type.group()) {
Ben Murdoch2385ea32013-08-06 11:01:04 +0100694 case NAME:
695 case NAME_BILLING:
Ben Murdocheb525c52013-07-10 11:40:50 +0100696 CopyItemsToValues(type, name_, app_locale, values);
697 break;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100698 case EMAIL:
Ben Murdocheb525c52013-07-10 11:40:50 +0100699 CopyItemsToValues(type, email_, app_locale, values);
700 break;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100701 case PHONE_HOME:
702 case PHONE_BILLING:
Ben Murdocheb525c52013-07-10 11:40:50 +0100703 CopyItemsToValues(type, phone_number_, app_locale, values);
704 break;
705 default:
706 values->resize(1);
707 (*values)[0] = GetFormGroupInfo(*this, type, app_locale);
708 }
709}
710
711void AutofillProfile::AddPhoneIfUnique(
712 const base::string16& phone,
713 const std::string& app_locale,
714 std::vector<base::string16>* existing_phones) {
715 DCHECK(existing_phones);
716 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
717 // "(800)356-9377" and "356-9377" are considered the same.
718 std::string country_code = UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY));
719 if (std::find_if(existing_phones->begin(), existing_phones->end(),
720 FindByPhone(phone, country_code, app_locale)) ==
721 existing_phones->end()) {
722 existing_phones->push_back(phone);
723 }
724}
725
726base::string16 AutofillProfile::ConstructInferredLabel(
Ben Murdoch32409262013-08-07 11:04:47 +0100727 const std::vector<ServerFieldType>& included_fields,
Ben Murdocheb525c52013-07-10 11:40:50 +0100728 size_t num_fields_to_use) const {
729 const base::string16 separator =
730 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR);
731
732 base::string16 label;
733 size_t num_fields_used = 0;
Ben Murdoch32409262013-08-07 11:04:47 +0100734 for (std::vector<ServerFieldType>::const_iterator it =
Ben Murdocheb525c52013-07-10 11:40:50 +0100735 included_fields.begin();
736 it != included_fields.end() && num_fields_used < num_fields_to_use;
737 ++it) {
738 base::string16 field = GetRawInfo(*it);
739 if (field.empty())
740 continue;
741
742 if (!label.empty())
743 label.append(separator);
744
745 label.append(field);
746 ++num_fields_used;
747 }
748 return label;
749}
750
751// static
752void AutofillProfile::CreateDifferentiatingLabels(
753 const std::vector<AutofillProfile*>& profiles,
754 const std::list<size_t>& indices,
Ben Murdoch32409262013-08-07 11:04:47 +0100755 const std::vector<ServerFieldType>& fields,
Ben Murdocheb525c52013-07-10 11:40:50 +0100756 size_t num_fields_to_include,
757 std::vector<base::string16>* created_labels) {
758 // For efficiency, we first construct a map of fields to their text values and
759 // each value's frequency.
Ben Murdoch32409262013-08-07 11:04:47 +0100760 std::map<ServerFieldType,
Ben Murdocheb525c52013-07-10 11:40:50 +0100761 std::map<base::string16, size_t> > field_text_frequencies_by_field;
Ben Murdoch32409262013-08-07 11:04:47 +0100762 for (std::vector<ServerFieldType>::const_iterator field = fields.begin();
Ben Murdocheb525c52013-07-10 11:40:50 +0100763 field != fields.end(); ++field) {
764 std::map<base::string16, size_t>& field_text_frequencies =
765 field_text_frequencies_by_field[*field];
766
767 for (std::list<size_t>::const_iterator it = indices.begin();
768 it != indices.end(); ++it) {
769 const AutofillProfile* profile = profiles[*it];
770 base::string16 field_text = profile->GetRawInfo(*field);
771
772 // If this label is not already in the map, add it with frequency 0.
773 if (!field_text_frequencies.count(field_text))
774 field_text_frequencies[field_text] = 0;
775
776 // Now, increment the frequency for this label.
777 ++field_text_frequencies[field_text];
778 }
779 }
780
781 // Now comes the meat of the algorithm. For each profile, we scan the list of
782 // fields to use, looking for two things:
783 // 1. A (non-empty) field that differentiates the profile from all others
784 // 2. At least |num_fields_to_include| non-empty fields
785 // Before we've satisfied condition (2), we include all fields, even ones that
786 // are identical across all the profiles. Once we've satisfied condition (2),
787 // we only include fields that that have at last two distinct values.
788 for (std::list<size_t>::const_iterator it = indices.begin();
789 it != indices.end(); ++it) {
790 const AutofillProfile* profile = profiles[*it];
791
Ben Murdoch32409262013-08-07 11:04:47 +0100792 std::vector<ServerFieldType> label_fields;
Ben Murdocheb525c52013-07-10 11:40:50 +0100793 bool found_differentiating_field = false;
Ben Murdoch32409262013-08-07 11:04:47 +0100794 for (std::vector<ServerFieldType>::const_iterator field = fields.begin();
Ben Murdocheb525c52013-07-10 11:40:50 +0100795 field != fields.end(); ++field) {
796 // Skip over empty fields.
797 base::string16 field_text = profile->GetRawInfo(*field);
798 if (field_text.empty())
799 continue;
800
801 std::map<base::string16, size_t>& field_text_frequencies =
802 field_text_frequencies_by_field[*field];
803 found_differentiating_field |=
804 !field_text_frequencies.count(base::string16()) &&
805 (field_text_frequencies[field_text] == 1);
806
807 // Once we've found enough non-empty fields, skip over any remaining
808 // fields that are identical across all the profiles.
809 if (label_fields.size() >= num_fields_to_include &&
810 (field_text_frequencies.size() == 1))
811 continue;
812
813 label_fields.push_back(*field);
814
815 // If we've (1) found a differentiating field and (2) found at least
816 // |num_fields_to_include| non-empty fields, we're done!
817 if (found_differentiating_field &&
818 label_fields.size() >= num_fields_to_include)
819 break;
820 }
821
822 (*created_labels)[*it] =
823 profile->ConstructInferredLabel(label_fields,
824 label_fields.size());
825 }
826}
827
828AutofillProfile::FormGroupList AutofillProfile::FormGroups() const {
829 FormGroupList v(5);
830 v[0] = &name_[0];
831 v[1] = &email_[0];
832 v[2] = &company_;
833 v[3] = &phone_number_[0];
834 v[4] = &address_;
835 return v;
836}
837
838const FormGroup* AutofillProfile::FormGroupForType(
Ben Murdoch32409262013-08-07 11:04:47 +0100839 const AutofillType& type) const {
Ben Murdocheb525c52013-07-10 11:40:50 +0100840 return const_cast<AutofillProfile*>(this)->MutableFormGroupForType(type);
841}
842
Ben Murdoch32409262013-08-07 11:04:47 +0100843FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) {
844 switch (type.group()) {
Ben Murdoch2385ea32013-08-06 11:01:04 +0100845 case NAME:
846 case NAME_BILLING:
Ben Murdoch32409262013-08-07 11:04:47 +0100847 return &name_[0];
848
Ben Murdoch2385ea32013-08-06 11:01:04 +0100849 case EMAIL:
Ben Murdoch32409262013-08-07 11:04:47 +0100850 return &email_[0];
851
Ben Murdoch2385ea32013-08-06 11:01:04 +0100852 case COMPANY:
Ben Murdoch32409262013-08-07 11:04:47 +0100853 return &company_;
854
Ben Murdoch2385ea32013-08-06 11:01:04 +0100855 case PHONE_HOME:
856 case PHONE_BILLING:
Ben Murdoch32409262013-08-07 11:04:47 +0100857 return &phone_number_[0];
858
Ben Murdoch2385ea32013-08-06 11:01:04 +0100859 case ADDRESS_HOME:
860 case ADDRESS_BILLING:
Ben Murdoch32409262013-08-07 11:04:47 +0100861 return &address_;
862
863 case NO_GROUP:
864 case CREDIT_CARD:
865 return NULL;
Ben Murdocheb525c52013-07-10 11:40:50 +0100866 }
867
Ben Murdoch32409262013-08-07 11:04:47 +0100868 NOTREACHED();
869 return NULL;
Ben Murdocheb525c52013-07-10 11:40:50 +0100870}
871
872// So we can compare AutofillProfiles with EXPECT_EQ().
873std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
874 return os
875 << UTF16ToUTF8(profile.Label())
876 << " "
877 << profile.guid()
878 << " "
879 << profile.origin()
880 << " "
881 << UTF16ToUTF8(MultiString(profile, NAME_FIRST))
882 << " "
883 << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE))
884 << " "
885 << UTF16ToUTF8(MultiString(profile, NAME_LAST))
886 << " "
887 << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS))
888 << " "
889 << UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME))
890 << " "
891 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1))
892 << " "
893 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2))
894 << " "
895 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY))
896 << " "
897 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE))
898 << " "
899 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP))
900 << " "
901 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))
902 << " "
903 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER));
904}
905
906} // namespace autofill