Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(765)

Unified Diff: components/autofill/browser/autofill_profile.cc

Issue 17392006: In components/autofill, move browser/ to core/browser/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to fix conflicts Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/browser/autofill_profile.cc
diff --git a/components/autofill/browser/autofill_profile.cc b/components/autofill/browser/autofill_profile.cc
deleted file mode 100644
index 3b9e303bd1eb919e9919eb9668d77e1b223d6b4c..0000000000000000000000000000000000000000
--- a/components/autofill/browser/autofill_profile.cc
+++ /dev/null
@@ -1,873 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/browser/autofill_profile.h"
-
-#include <algorithm>
-#include <functional>
-#include <map>
-#include <ostream>
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/guid.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/browser/address.h"
-#include "components/autofill/browser/autofill_country.h"
-#include "components/autofill/browser/autofill_field.h"
-#include "components/autofill/browser/autofill_type.h"
-#include "components/autofill/browser/contact_info.h"
-#include "components/autofill/browser/phone_number.h"
-#include "components/autofill/browser/phone_number_i18n.h"
-#include "components/autofill/core/common/form_field_data.h"
-#include "grit/component_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace autofill {
-namespace {
-
-// Like |AutofillType::GetEquivalentFieldType()|, but also returns |NAME_FULL|
-// for first, middle, and last name field types.
-AutofillFieldType GetEquivalentFieldTypeCollapsingNames(
- AutofillFieldType field_type) {
- if (field_type == NAME_FIRST || field_type == NAME_MIDDLE ||
- field_type == NAME_LAST || field_type == NAME_MIDDLE_INITIAL)
- return NAME_FULL;
-
- return AutofillType::GetEquivalentFieldType(field_type);
-}
-
-// Fills |distinguishing_fields| with a list of fields to use when creating
-// labels that can help to distinguish between two profiles. Draws fields from
-// |suggested_fields| if it is non-NULL; otherwise returns a default list.
-// If |suggested_fields| is non-NULL, does not include |excluded_field| in the
-// list. Otherwise, |excluded_field| is ignored, and should be set to
-// |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in
-// decreasing order of importance.
-void GetFieldsForDistinguishingProfiles(
- const std::vector<AutofillFieldType>* suggested_fields,
- AutofillFieldType excluded_field,
- std::vector<AutofillFieldType>* distinguishing_fields) {
- static const AutofillFieldType kDefaultDistinguishingFields[] = {
- NAME_FULL,
- ADDRESS_HOME_LINE1,
- ADDRESS_HOME_LINE2,
- ADDRESS_HOME_CITY,
- ADDRESS_HOME_STATE,
- ADDRESS_HOME_ZIP,
- ADDRESS_HOME_COUNTRY,
- EMAIL_ADDRESS,
- PHONE_HOME_WHOLE_NUMBER,
- COMPANY_NAME,
- };
-
- if (!suggested_fields) {
- DCHECK_EQ(excluded_field, UNKNOWN_TYPE);
- distinguishing_fields->assign(
- kDefaultDistinguishingFields,
- kDefaultDistinguishingFields + arraysize(kDefaultDistinguishingFields));
- return;
- }
-
- // Keep track of which fields we've seen so that we avoid duplicate entries.
- // Always ignore fields of unknown type and the excluded field.
- std::set<AutofillFieldType> seen_fields;
- seen_fields.insert(UNKNOWN_TYPE);
- seen_fields.insert(GetEquivalentFieldTypeCollapsingNames(excluded_field));
-
- distinguishing_fields->clear();
- for (std::vector<AutofillFieldType>::const_iterator it =
- suggested_fields->begin();
- it != suggested_fields->end(); ++it) {
- AutofillFieldType suggested_type =
- GetEquivalentFieldTypeCollapsingNames(*it);
- if (seen_fields.insert(suggested_type).second)
- distinguishing_fields->push_back(suggested_type);
- }
-
- // Special case: If the excluded field is a partial name (e.g. first name) and
- // the suggested fields include other name fields, include |NAME_FULL| in the
- // list of distinguishing fields as a last-ditch fallback. This allows us to
- // distinguish between profiles that are identical except for the name.
- if (excluded_field != NAME_FULL &&
- GetEquivalentFieldTypeCollapsingNames(excluded_field) == NAME_FULL) {
- for (std::vector<AutofillFieldType>::const_iterator it =
- suggested_fields->begin();
- it != suggested_fields->end(); ++it) {
- if (*it != excluded_field &&
- GetEquivalentFieldTypeCollapsingNames(*it) == NAME_FULL) {
- distinguishing_fields->push_back(NAME_FULL);
- break;
- }
- }
- }
-}
-
-// A helper function for string streaming. Concatenates multi-valued entries
-// stored for a given |type| into a single string. This string is returned.
-const base::string16 MultiString(const AutofillProfile& p,
- AutofillFieldType type) {
- std::vector<base::string16> values;
- p.GetRawMultiInfo(type, &values);
- base::string16 accumulate;
- for (size_t i = 0; i < values.size(); ++i) {
- if (i > 0)
- accumulate += ASCIIToUTF16(" ");
- accumulate += values[i];
- }
- return accumulate;
-}
-
-base::string16 GetFormGroupInfo(const FormGroup& form_group,
- AutofillFieldType type,
- const std::string& app_locale) {
- return app_locale.empty() ?
- form_group.GetRawInfo(type) :
- form_group.GetInfo(type, app_locale);
-}
-
-template <class T>
-void CopyValuesToItems(AutofillFieldType type,
- const std::vector<base::string16>& values,
- std::vector<T>* form_group_items,
- const T& prototype) {
- form_group_items->resize(values.size(), prototype);
- for (size_t i = 0; i < form_group_items->size(); ++i) {
- (*form_group_items)[i].SetRawInfo(type,
- CollapseWhitespace(values[i], false));
- }
- // Must have at least one (possibly empty) element.
- if (form_group_items->empty())
- form_group_items->resize(1, prototype);
-}
-
-template <class T>
-void CopyItemsToValues(AutofillFieldType type,
- const std::vector<T>& form_group_items,
- const std::string& app_locale,
- std::vector<base::string16>* values) {
- values->resize(form_group_items.size());
- for (size_t i = 0; i < values->size(); ++i) {
- (*values)[i] = GetFormGroupInfo(form_group_items[i], type, app_locale);
- }
-}
-
-// Collapse compound field types to their "full" type. I.e. First name
-// collapses to full name, area code collapses to full phone, etc.
-void CollapseCompoundFieldTypes(FieldTypeSet* type_set) {
- FieldTypeSet collapsed_set;
- for (FieldTypeSet::iterator iter = type_set->begin(); iter != type_set->end();
- ++iter) {
- switch (*iter) {
- case NAME_FIRST:
- case NAME_MIDDLE:
- case NAME_LAST:
- case NAME_MIDDLE_INITIAL:
- case NAME_FULL:
- case NAME_SUFFIX:
- collapsed_set.insert(NAME_FULL);
- break;
-
- case PHONE_HOME_NUMBER:
- case PHONE_HOME_CITY_CODE:
- case PHONE_HOME_COUNTRY_CODE:
- case PHONE_HOME_CITY_AND_NUMBER:
- case PHONE_HOME_WHOLE_NUMBER:
- collapsed_set.insert(PHONE_HOME_WHOLE_NUMBER);
- break;
-
- default:
- collapsed_set.insert(*iter);
- }
- }
- std::swap(*type_set, collapsed_set);
-}
-
-class FindByPhone {
- public:
- FindByPhone(const base::string16& phone,
- const std::string& country_code,
- const std::string& app_locale)
- : phone_(phone),
- country_code_(country_code),
- app_locale_(app_locale) {
- }
-
- bool operator()(const base::string16& phone) {
- return i18n::PhoneNumbersMatch(phone, phone_, country_code_, app_locale_);
- }
-
- bool operator()(const base::string16* phone) {
- return i18n::PhoneNumbersMatch(*phone, phone_, country_code_, app_locale_);
- }
-
- private:
- base::string16 phone_;
- std::string country_code_;
- std::string app_locale_;
-};
-
-// Functor used to check for case-insensitive equality of two strings.
-struct CaseInsensitiveStringEquals
- : public std::binary_function<base::string16, base::string16, bool>
-{
- bool operator()(const base::string16& x, const base::string16& y) const {
- return
- x.size() == y.size() && StringToLowerASCII(x) == StringToLowerASCII(y);
- }
-};
-
-} // namespace
-
-AutofillProfile::AutofillProfile(const std::string& guid,
- const std::string& origin)
- : AutofillDataModel(guid, origin),
- name_(1),
- email_(1),
- phone_number_(1, PhoneNumber(this)) {
-}
-
-AutofillProfile::AutofillProfile()
- : AutofillDataModel(base::GenerateGUID(), std::string()),
- name_(1),
- email_(1),
- phone_number_(1, PhoneNumber(this)) {
-}
-
-AutofillProfile::AutofillProfile(const AutofillProfile& profile)
- : AutofillDataModel(std::string(), std::string()) {
- operator=(profile);
-}
-
-AutofillProfile::~AutofillProfile() {
-}
-
-AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
- if (this == &profile)
- return *this;
-
- set_guid(profile.guid());
- set_origin(profile.origin());
-
- label_ = profile.label_;
- name_ = profile.name_;
- email_ = profile.email_;
- company_ = profile.company_;
- phone_number_ = profile.phone_number_;
-
- for (size_t i = 0; i < phone_number_.size(); ++i)
- phone_number_[i].set_profile(this);
-
- address_ = profile.address_;
-
- return *this;
-}
-
-void AutofillProfile::GetMatchingTypes(const base::string16& text,
- const std::string& app_locale,
- FieldTypeSet* matching_types) const {
- FormGroupList info = FormGroups();
- for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
- (*it)->GetMatchingTypes(text, app_locale, matching_types);
-}
-
-base::string16 AutofillProfile::GetRawInfo(AutofillFieldType type) const {
- AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type);
- const FormGroup* form_group = FormGroupForType(return_type);
- if (!form_group)
- return base::string16();
-
- return form_group->GetRawInfo(return_type);
-}
-
-void AutofillProfile::SetRawInfo(AutofillFieldType type,
- const base::string16& value) {
- FormGroup* form_group = MutableFormGroupForType(type);
- if (form_group)
- form_group->SetRawInfo(type, CollapseWhitespace(value, false));
-}
-
-base::string16 AutofillProfile::GetInfo(AutofillFieldType type,
- const std::string& app_locale) const {
- AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type);
- const FormGroup* form_group = FormGroupForType(return_type);
- if (!form_group)
- return base::string16();
-
- return form_group->GetInfo(return_type, app_locale);
-}
-
-bool AutofillProfile::SetInfo(AutofillFieldType type,
- const base::string16& value,
- const std::string& app_locale) {
- FormGroup* form_group = MutableFormGroupForType(type);
- if (!form_group)
- return false;
-
- return
- form_group->SetInfo(type, CollapseWhitespace(value, false), app_locale);
-}
-
-void AutofillProfile::SetRawMultiInfo(
- AutofillFieldType type,
- const std::vector<base::string16>& values) {
- switch (AutofillType(type).group()) {
- case AutofillType::NAME:
- CopyValuesToItems(type, values, &name_, NameInfo());
- break;
- case AutofillType::EMAIL:
- CopyValuesToItems(type, values, &email_, EmailInfo());
- break;
- case AutofillType::PHONE_HOME:
- case AutofillType::PHONE_BILLING:
- CopyValuesToItems(type,
- values,
- &phone_number_,
- PhoneNumber(this));
- break;
- default:
- if (values.size() == 1) {
- SetRawInfo(type, values[0]);
- } else if (values.size() == 0) {
- SetRawInfo(type, base::string16());
- } else {
- // Shouldn't attempt to set multiple values on single-valued field.
- NOTREACHED();
- }
- break;
- }
-}
-
-void AutofillProfile::GetRawMultiInfo(
- AutofillFieldType type,
- std::vector<base::string16>* values) const {
- GetMultiInfoImpl(type, std::string(), values);
-}
-
-void AutofillProfile::GetMultiInfo(AutofillFieldType type,
- const std::string& app_locale,
- std::vector<base::string16>* values) const {
- GetMultiInfoImpl(type, app_locale, values);
-}
-
-void AutofillProfile::FillFormField(const AutofillField& field,
- size_t variant,
- const std::string& app_locale,
- FormFieldData* field_data) const {
- AutofillFieldType type = field.type();
- DCHECK_NE(AutofillType::CREDIT_CARD, AutofillType(type).group());
- DCHECK(field_data);
-
- if (type == PHONE_HOME_NUMBER || type == PHONE_BILLING_NUMBER) {
- FillPhoneNumberField(field, variant, app_locale, field_data);
- } else if (field_data->form_control_type == "select-one") {
- FillSelectControl(type, app_locale, field_data);
- } else {
- std::vector<base::string16> values;
- GetMultiInfo(type, app_locale, &values);
- if (variant >= values.size()) {
- // If the variant is unavailable, bail. This case is reachable, for
- // example if Sync updates a profile during the filling process.
- return;
- }
-
- field_data->value = values[variant];
- }
-}
-
-void AutofillProfile::FillPhoneNumberField(const AutofillField& field,
- size_t variant,
- const std::string& app_locale,
- FormFieldData* field_data) const {
- std::vector<base::string16> values;
- GetMultiInfo(field.type(), app_locale, &values);
- DCHECK(variant < values.size());
-
- // If we are filling a phone number, check to see if the size field
- // matches the "prefix" or "suffix" sizes and fill accordingly.
- base::string16 number = values[variant];
- if (number.length() ==
- PhoneNumber::kPrefixLength + PhoneNumber::kSuffixLength) {
- if (field.phone_part() == AutofillField::PHONE_PREFIX ||
- field_data->max_length == PhoneNumber::kPrefixLength) {
- number = number.substr(PhoneNumber::kPrefixOffset,
- PhoneNumber::kPrefixLength);
- } else if (field.phone_part() == AutofillField::PHONE_SUFFIX ||
- field_data->max_length == PhoneNumber::kSuffixLength) {
- number = number.substr(PhoneNumber::kSuffixOffset,
- PhoneNumber::kSuffixLength);
- }
- }
-
- field_data->value = number;
-}
-
-const base::string16 AutofillProfile::Label() const {
- return label_;
-}
-
-bool AutofillProfile::IsEmpty(const std::string& app_locale) const {
- FieldTypeSet types;
- GetNonEmptyTypes(app_locale, &types);
- return types.empty();
-}
-
-int AutofillProfile::Compare(const AutofillProfile& profile) const {
- const AutofillFieldType single_value_types[] = { COMPANY_NAME,
- ADDRESS_HOME_LINE1,
- ADDRESS_HOME_LINE2,
- ADDRESS_HOME_CITY,
- ADDRESS_HOME_STATE,
- ADDRESS_HOME_ZIP,
- ADDRESS_HOME_COUNTRY };
-
- for (size_t i = 0; i < arraysize(single_value_types); ++i) {
- int comparison = GetRawInfo(single_value_types[i]).compare(
- profile.GetRawInfo(single_value_types[i]));
- if (comparison != 0)
- return comparison;
- }
-
- const AutofillFieldType multi_value_types[] = { NAME_FIRST,
- NAME_MIDDLE,
- NAME_LAST,
- EMAIL_ADDRESS,
- PHONE_HOME_WHOLE_NUMBER };
-
- for (size_t i = 0; i < arraysize(multi_value_types); ++i) {
- std::vector<base::string16> values_a;
- std::vector<base::string16> values_b;
- GetRawMultiInfo(multi_value_types[i], &values_a);
- profile.GetRawMultiInfo(multi_value_types[i], &values_b);
- if (values_a.size() < values_b.size())
- return -1;
- if (values_a.size() > values_b.size())
- return 1;
- for (size_t j = 0; j < values_a.size(); ++j) {
- int comparison = values_a[j].compare(values_b[j]);
- if (comparison != 0)
- return comparison;
- }
- }
-
- return 0;
-}
-
-bool AutofillProfile::operator==(const AutofillProfile& profile) const {
- return guid() == profile.guid() &&
- origin() == profile.origin() &&
- Compare(profile) == 0;
-}
-
-bool AutofillProfile::operator!=(const AutofillProfile& profile) const {
- return !operator==(profile);
-}
-
-const base::string16 AutofillProfile::PrimaryValue() const {
- return GetRawInfo(ADDRESS_HOME_LINE1) + GetRawInfo(ADDRESS_HOME_CITY);
-}
-
-bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile,
- const std::string& app_locale) const {
- FieldTypeSet types;
- GetNonEmptyTypes(app_locale, &types);
-
- for (FieldTypeSet::const_iterator iter = types.begin(); iter != types.end();
- ++iter) {
- if (*iter == NAME_FULL) {
- // Ignore the compound "full name" field type. We are only interested in
- // comparing the constituent parts. For example, if |this| has a middle
- // name saved, but |profile| lacks one, |profile| could still be a subset
- // of |this|.
- continue;
- } else if (AutofillType(*iter).group() == AutofillType::PHONE_HOME) {
- // Phone numbers should be canonicalized prior to being compared.
- if (*iter != PHONE_HOME_WHOLE_NUMBER) {
- continue;
- } else if (!i18n::PhoneNumbersMatch(
- GetRawInfo(*iter),
- profile.GetRawInfo(*iter),
- UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)),
- app_locale)) {
- return false;
- }
- } else if (StringToLowerASCII(GetRawInfo(*iter)) !=
- StringToLowerASCII(profile.GetRawInfo(*iter))) {
- return false;
- }
- }
-
- return true;
-}
-
-void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile,
- const std::string& app_locale) {
- // Verified profiles should never be overwritten with unverified data.
- DCHECK(!IsVerified() || profile.IsVerified());
- set_origin(profile.origin());
-
- FieldTypeSet field_types;
- profile.GetNonEmptyTypes(app_locale, &field_types);
-
- // Only transfer "full" types (e.g. full name) and not fragments (e.g.
- // first name, last name).
- CollapseCompoundFieldTypes(&field_types);
-
- for (FieldTypeSet::const_iterator iter = field_types.begin();
- iter != field_types.end(); ++iter) {
- if (AutofillProfile::SupportsMultiValue(*iter)) {
- std::vector<base::string16> new_values;
- profile.GetRawMultiInfo(*iter, &new_values);
- std::vector<base::string16> existing_values;
- GetRawMultiInfo(*iter, &existing_values);
-
- // GetMultiInfo always returns at least one element, even if the profile
- // has no data stored for this field type.
- if (existing_values.size() == 1 && existing_values.front().empty())
- existing_values.clear();
-
- FieldTypeGroup group = AutofillType(*iter).group();
- for (std::vector<base::string16>::iterator value_iter =
- new_values.begin();
- value_iter != new_values.end(); ++value_iter) {
- // Don't add duplicates.
- if (group == AutofillType::PHONE_HOME) {
- AddPhoneIfUnique(*value_iter, app_locale, &existing_values);
- } else {
- std::vector<base::string16>::const_iterator existing_iter =
- std::find_if(
- existing_values.begin(), existing_values.end(),
- std::bind1st(CaseInsensitiveStringEquals(), *value_iter));
- if (existing_iter == existing_values.end())
- existing_values.insert(existing_values.end(), *value_iter);
- }
- }
- SetRawMultiInfo(*iter, existing_values);
- } else {
- base::string16 new_value = profile.GetRawInfo(*iter);
- if (StringToLowerASCII(GetRawInfo(*iter)) !=
- StringToLowerASCII(new_value)) {
- SetRawInfo(*iter, new_value);
- }
- }
- }
-}
-
-// static
-bool AutofillProfile::SupportsMultiValue(AutofillFieldType type) {
- AutofillType::FieldTypeGroup group = AutofillType(type).group();
- return group == AutofillType::NAME ||
- group == AutofillType::EMAIL ||
- group == AutofillType::PHONE_HOME ||
- group == AutofillType::PHONE_BILLING;
-}
-
-// static
-bool AutofillProfile::AdjustInferredLabels(
- std::vector<AutofillProfile*>* profiles) {
- const size_t kMinimalFieldsShown = 2;
-
- std::vector<base::string16> created_labels;
- CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown,
- &created_labels);
- DCHECK_EQ(profiles->size(), created_labels.size());
-
- bool updated_labels = false;
- for (size_t i = 0; i < profiles->size(); ++i) {
- if ((*profiles)[i]->Label() != created_labels[i]) {
- updated_labels = true;
- (*profiles)[i]->label_ = created_labels[i];
- }
- }
- return updated_labels;
-}
-
-// static
-void AutofillProfile::CreateInferredLabels(
- const std::vector<AutofillProfile*>* profiles,
- const std::vector<AutofillFieldType>* suggested_fields,
- AutofillFieldType excluded_field,
- size_t minimal_fields_shown,
- std::vector<base::string16>* created_labels) {
- DCHECK(profiles);
- DCHECK(created_labels);
-
- std::vector<AutofillFieldType> fields_to_use;
- GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field,
- &fields_to_use);
-
- // Construct the default label for each profile. Also construct a map that
- // associates each label with the profiles that have this label. This map is
- // then used to detect which labels need further differentiating fields.
- std::map<base::string16, std::list<size_t> > labels;
- for (size_t i = 0; i < profiles->size(); ++i) {
- base::string16 label =
- (*profiles)[i]->ConstructInferredLabel(fields_to_use,
- minimal_fields_shown);
- labels[label].push_back(i);
- }
-
- created_labels->resize(profiles->size());
- for (std::map<base::string16, std::list<size_t> >::const_iterator it =
- labels.begin();
- it != labels.end(); ++it) {
- if (it->second.size() == 1) {
- // This label is unique, so use it without any further ado.
- base::string16 label = it->first;
- size_t profile_index = it->second.front();
- (*created_labels)[profile_index] = label;
- } else {
- // We have more than one profile with the same label, so add
- // differentiating fields.
- CreateDifferentiatingLabels(*profiles, it->second, fields_to_use,
- minimal_fields_shown, created_labels);
- }
- }
-}
-
-void AutofillProfile::GetSupportedTypes(FieldTypeSet* supported_types) const {
- FormGroupList info = FormGroups();
- for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
- (*it)->GetSupportedTypes(supported_types);
-}
-
-bool AutofillProfile::FillCountrySelectControl(
- const std::string& app_locale,
- FormFieldData* field_data) const {
- std::string country_code = UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY));
-
- DCHECK_EQ(field_data->option_values.size(),
- field_data->option_contents.size());
- for (size_t i = 0; i < field_data->option_values.size(); ++i) {
- // Canonicalize each <option> value to a country code, and compare to the
- // target country code.
- base::string16 value = field_data->option_values[i];
- base::string16 contents = field_data->option_contents[i];
- if (country_code == AutofillCountry::GetCountryCode(value, app_locale) ||
- country_code == AutofillCountry::GetCountryCode(contents, app_locale)) {
- field_data->value = value;
- return true;
- }
- }
-
- return false;
-}
-
-void AutofillProfile::GetMultiInfoImpl(
- AutofillFieldType type,
- const std::string& app_locale,
- std::vector<base::string16>* values) const {
- switch (AutofillType(type).group()) {
- case AutofillType::NAME:
- CopyItemsToValues(type, name_, app_locale, values);
- break;
- case AutofillType::EMAIL:
- CopyItemsToValues(type, email_, app_locale, values);
- break;
- case AutofillType::PHONE_HOME:
- case AutofillType::PHONE_BILLING:
- CopyItemsToValues(type, phone_number_, app_locale, values);
- break;
- default:
- values->resize(1);
- (*values)[0] = GetFormGroupInfo(*this, type, app_locale);
- }
-}
-
-void AutofillProfile::AddPhoneIfUnique(
- const base::string16& phone,
- const std::string& app_locale,
- std::vector<base::string16>* existing_phones) {
- DCHECK(existing_phones);
- // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
- // "(800)356-9377" and "356-9377" are considered the same.
- std::string country_code = UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY));
- if (std::find_if(existing_phones->begin(), existing_phones->end(),
- FindByPhone(phone, country_code, app_locale)) ==
- existing_phones->end()) {
- existing_phones->push_back(phone);
- }
-}
-
-base::string16 AutofillProfile::ConstructInferredLabel(
- const std::vector<AutofillFieldType>& included_fields,
- size_t num_fields_to_use) const {
- const base::string16 separator =
- l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR);
-
- base::string16 label;
- size_t num_fields_used = 0;
- for (std::vector<AutofillFieldType>::const_iterator it =
- included_fields.begin();
- it != included_fields.end() && num_fields_used < num_fields_to_use;
- ++it) {
- base::string16 field = GetRawInfo(*it);
- if (field.empty())
- continue;
-
- if (!label.empty())
- label.append(separator);
-
- label.append(field);
- ++num_fields_used;
- }
- return label;
-}
-
-// static
-void AutofillProfile::CreateDifferentiatingLabels(
- const std::vector<AutofillProfile*>& profiles,
- const std::list<size_t>& indices,
- const std::vector<AutofillFieldType>& fields,
- size_t num_fields_to_include,
- std::vector<base::string16>* created_labels) {
- // For efficiency, we first construct a map of fields to their text values and
- // each value's frequency.
- std::map<AutofillFieldType,
- std::map<base::string16, size_t> > field_text_frequencies_by_field;
- for (std::vector<AutofillFieldType>::const_iterator field = fields.begin();
- field != fields.end(); ++field) {
- std::map<base::string16, size_t>& field_text_frequencies =
- field_text_frequencies_by_field[*field];
-
- for (std::list<size_t>::const_iterator it = indices.begin();
- it != indices.end(); ++it) {
- const AutofillProfile* profile = profiles[*it];
- base::string16 field_text = profile->GetRawInfo(*field);
-
- // If this label is not already in the map, add it with frequency 0.
- if (!field_text_frequencies.count(field_text))
- field_text_frequencies[field_text] = 0;
-
- // Now, increment the frequency for this label.
- ++field_text_frequencies[field_text];
- }
- }
-
- // Now comes the meat of the algorithm. For each profile, we scan the list of
- // fields to use, looking for two things:
- // 1. A (non-empty) field that differentiates the profile from all others
- // 2. At least |num_fields_to_include| non-empty fields
- // Before we've satisfied condition (2), we include all fields, even ones that
- // are identical across all the profiles. Once we've satisfied condition (2),
- // we only include fields that that have at last two distinct values.
- for (std::list<size_t>::const_iterator it = indices.begin();
- it != indices.end(); ++it) {
- const AutofillProfile* profile = profiles[*it];
-
- std::vector<AutofillFieldType> label_fields;
- bool found_differentiating_field = false;
- for (std::vector<AutofillFieldType>::const_iterator field = fields.begin();
- field != fields.end(); ++field) {
- // Skip over empty fields.
- base::string16 field_text = profile->GetRawInfo(*field);
- if (field_text.empty())
- continue;
-
- std::map<base::string16, size_t>& field_text_frequencies =
- field_text_frequencies_by_field[*field];
- found_differentiating_field |=
- !field_text_frequencies.count(base::string16()) &&
- (field_text_frequencies[field_text] == 1);
-
- // Once we've found enough non-empty fields, skip over any remaining
- // fields that are identical across all the profiles.
- if (label_fields.size() >= num_fields_to_include &&
- (field_text_frequencies.size() == 1))
- continue;
-
- label_fields.push_back(*field);
-
- // If we've (1) found a differentiating field and (2) found at least
- // |num_fields_to_include| non-empty fields, we're done!
- if (found_differentiating_field &&
- label_fields.size() >= num_fields_to_include)
- break;
- }
-
- (*created_labels)[*it] =
- profile->ConstructInferredLabel(label_fields,
- label_fields.size());
- }
-}
-
-AutofillProfile::FormGroupList AutofillProfile::FormGroups() const {
- FormGroupList v(5);
- v[0] = &name_[0];
- v[1] = &email_[0];
- v[2] = &company_;
- v[3] = &phone_number_[0];
- v[4] = &address_;
- return v;
-}
-
-const FormGroup* AutofillProfile::FormGroupForType(
- AutofillFieldType type) const {
- return const_cast<AutofillProfile*>(this)->MutableFormGroupForType(type);
-}
-
-FormGroup* AutofillProfile::MutableFormGroupForType(AutofillFieldType type) {
- FormGroup* form_group = NULL;
- switch (AutofillType(type).group()) {
- case AutofillType::NAME:
- form_group = &name_[0];
- break;
- case AutofillType::EMAIL:
- form_group = &email_[0];
- break;
- case AutofillType::COMPANY:
- form_group = &company_;
- break;
- case AutofillType::PHONE_HOME:
- case AutofillType::PHONE_BILLING:
- form_group = &phone_number_[0];
- break;
- case AutofillType::ADDRESS_HOME:
- case AutofillType::ADDRESS_BILLING:
- form_group = &address_;
- break;
- default:
- break;
- }
-
- return form_group;
-}
-
-// So we can compare AutofillProfiles with EXPECT_EQ().
-std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
- return os
- << UTF16ToUTF8(profile.Label())
- << " "
- << profile.guid()
- << " "
- << profile.origin()
- << " "
- << UTF16ToUTF8(MultiString(profile, NAME_FIRST))
- << " "
- << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE))
- << " "
- << UTF16ToUTF8(MultiString(profile, NAME_LAST))
- << " "
- << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS))
- << " "
- << UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME))
- << " "
- << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1))
- << " "
- << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2))
- << " "
- << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY))
- << " "
- << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE))
- << " "
- << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP))
- << " "
- << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))
- << " "
- << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER));
-}
-
-} // namespace autofill
« no previous file with comments | « components/autofill/browser/autofill_profile.h ('k') | components/autofill/browser/autofill_profile_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698