blob: 813d61556914a761913f715715e3ee06bed498b5 [file] [log] [blame]
// Copyright 2013 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/core/browser/address.h"
#include <stddef.h>
#include <algorithm>
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_profile_comparator.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/state_names.h"
#include "components/autofill/core/common/autofill_l10n_util.h"
namespace autofill {
Address::Address() {}
Address::Address(const Address& address) : FormGroup() {
*this = address;
}
Address::~Address() {}
Address& Address::operator=(const Address& address) {
if (this == &address)
return *this;
street_address_ = address.street_address_;
dependent_locality_ = address.dependent_locality_;
city_ = address.city_;
state_ = address.state_;
country_code_ = address.country_code_;
zip_code_ = address.zip_code_;
sorting_code_ = address.sorting_code_;
return *this;
}
bool Address::operator==(const Address& other) const {
if (this == &other)
return true;
return street_address_ == other.street_address_ &&
dependent_locality_ == other.dependent_locality_ &&
city_ == other.city_ && state_ == other.state_ &&
zip_code_ == other.zip_code_ && sorting_code_ == other.sorting_code_ &&
country_code_ == other.country_code_;
}
base::string16 Address::GetRawInfo(ServerFieldType type) const {
DCHECK_EQ(ADDRESS_HOME, AutofillType(type).group());
switch (type) {
case ADDRESS_HOME_LINE1:
return street_address_.size() > 0 ? street_address_[0] : base::string16();
case ADDRESS_HOME_LINE2:
return street_address_.size() > 1 ? street_address_[1] : base::string16();
case ADDRESS_HOME_LINE3:
return street_address_.size() > 2 ? street_address_[2] : base::string16();
case ADDRESS_HOME_DEPENDENT_LOCALITY:
return dependent_locality_;
case ADDRESS_HOME_CITY:
return city_;
case ADDRESS_HOME_STATE:
return state_;
case ADDRESS_HOME_ZIP:
return zip_code_;
case ADDRESS_HOME_SORTING_CODE:
return sorting_code_;
case ADDRESS_HOME_COUNTRY:
return base::ASCIIToUTF16(country_code_);
case ADDRESS_HOME_STREET_ADDRESS:
return base::JoinString(street_address_, base::ASCIIToUTF16("\n"));
case ADDRESS_HOME_APT_NUM:
return base::string16();
default:
NOTREACHED() << "Unrecognized type: " << type;
return base::string16();
}
}
void Address::SetRawInfo(ServerFieldType type, const base::string16& value) {
DCHECK_EQ(ADDRESS_HOME, AutofillType(type).group());
switch (type) {
case ADDRESS_HOME_LINE1:
if (street_address_.empty())
street_address_.resize(1);
street_address_[0] = value;
TrimStreetAddress();
break;
case ADDRESS_HOME_LINE2:
if (street_address_.size() < 2)
street_address_.resize(2);
street_address_[1] = value;
TrimStreetAddress();
break;
case ADDRESS_HOME_LINE3:
if (street_address_.size() < 3)
street_address_.resize(3);
street_address_[2] = value;
TrimStreetAddress();
break;
case ADDRESS_HOME_DEPENDENT_LOCALITY:
dependent_locality_ = value;
break;
case ADDRESS_HOME_CITY:
city_ = value;
break;
case ADDRESS_HOME_STATE:
state_ = value;
break;
case ADDRESS_HOME_COUNTRY:
DCHECK(value.empty() ||
(value.length() == 2u && base::IsStringASCII(value)));
country_code_ = base::UTF16ToASCII(value);
break;
case ADDRESS_HOME_ZIP:
zip_code_ = value;
break;
case ADDRESS_HOME_SORTING_CODE:
sorting_code_ = value;
break;
case ADDRESS_HOME_STREET_ADDRESS:
street_address_ = base::SplitString(
value, base::ASCIIToUTF16("\n"),
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
break;
default:
NOTREACHED();
}
}
base::string16 Address::GetInfo(const AutofillType& type,
const std::string& app_locale) const {
if (type.html_type() == HTML_TYPE_COUNTRY_CODE)
return base::ASCIIToUTF16(country_code_);
ServerFieldType storable_type = type.GetStorableType();
if (storable_type == ADDRESS_HOME_COUNTRY && !country_code_.empty())
return AutofillCountry(country_code_, app_locale).name();
return GetRawInfo(storable_type);
}
bool Address::SetInfo(const AutofillType& type,
const base::string16& value,
const std::string& app_locale) {
if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
if (!value.empty() && (value.size() != 2u || !base::IsStringASCII(value))) {
country_code_ = std::string();
return false;
}
country_code_ = base::ToUpperASCII(base::UTF16ToASCII(value));
return true;
} else if (type.html_type() == HTML_TYPE_FULL_ADDRESS) {
// Parsing a full address is too hard.
return false;
}
ServerFieldType storable_type = type.GetStorableType();
if (storable_type == ADDRESS_HOME_COUNTRY && !value.empty()) {
country_code_ = CountryNames::GetInstance()->GetCountryCode(value);
return !country_code_.empty();
}
SetRawInfo(storable_type, value);
// Give up when importing addresses with any entirely blank lines.
// There's a good chance that this formatting is not intentional, but it's
// also not obviously safe to just strip the newlines.
if (storable_type == ADDRESS_HOME_STREET_ADDRESS &&
std::find(street_address_.begin(), street_address_.end(),
base::string16()) != street_address_.end()) {
street_address_.clear();
return false;
}
return true;
}
void Address::GetMatchingTypes(const base::string16& text,
const std::string& app_locale,
ServerFieldTypeSet* matching_types) const {
FormGroup::GetMatchingTypes(text, app_locale, matching_types);
// Check to see if the |text| canonicalized as a country name is a match.
std::string country_code = CountryNames::GetInstance()->GetCountryCode(text);
if (!country_code.empty() && country_code_ == country_code)
matching_types->insert(ADDRESS_HOME_COUNTRY);
AutofillProfileComparator comparator(app_locale);
// Check to see if the |text| could be the full name or abbreviation of a
// state.
base::string16 canon_text = comparator.NormalizeForComparison(text);
base::string16 state_name;
base::string16 state_abbreviation;
state_names::GetNameAndAbbreviation(canon_text, &state_name,
&state_abbreviation);
if (!state_name.empty() || !state_abbreviation.empty()) {
l10n::CaseInsensitiveCompare compare;
base::string16 canon_profile_state =
comparator.NormalizeForComparison(
GetInfo(AutofillType(ADDRESS_HOME_STATE), app_locale));
if ((!state_name.empty() &&
compare.StringsEqual(state_name, canon_profile_state)) ||
(!state_abbreviation.empty() &&
compare.StringsEqual(state_abbreviation, canon_profile_state))) {
matching_types->insert(ADDRESS_HOME_STATE);
}
}
}
void Address::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
supported_types->insert(ADDRESS_HOME_LINE1);
supported_types->insert(ADDRESS_HOME_LINE2);
supported_types->insert(ADDRESS_HOME_LINE3);
supported_types->insert(ADDRESS_HOME_STREET_ADDRESS);
supported_types->insert(ADDRESS_HOME_DEPENDENT_LOCALITY);
supported_types->insert(ADDRESS_HOME_CITY);
supported_types->insert(ADDRESS_HOME_STATE);
supported_types->insert(ADDRESS_HOME_ZIP);
supported_types->insert(ADDRESS_HOME_SORTING_CODE);
supported_types->insert(ADDRESS_HOME_COUNTRY);
}
void Address::TrimStreetAddress() {
while (!street_address_.empty() && street_address_.back().empty()) {
street_address_.pop_back();
}
}
} // namespace autofill