1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
// Copyright 2013 The Chromium Authors
// 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/geo/autofill_country.h"
#include <stddef.h>
#include <array>
#include "base/containers/contains.h"
#include "base/containers/fixed_flat_map.h"
#include "base/containers/fixed_flat_set.h"
#include "base/feature_list.h"
#include "base/strings/string_util.h"
#include "components/autofill/core/browser/geo/address_i18n.h"
#include "components/autofill/core/browser/geo/country_data.h"
#include "components/autofill/core/browser/geo/country_names.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_internals/log_message.h"
#include "components/autofill/core/common/logging/log_buffer.h"
#include "components/strings/grit/components_strings.h"
#include "third_party/icu/source/common/unicode/locid.h"
#include "third_party/libaddressinput/messages.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
namespace {
// The maximum capacity needed to store a locale up to the country code.
constexpr size_t kLocaleCapacity =
ULOC_LANG_CAPACITY + ULOC_SCRIPT_CAPACITY + ULOC_COUNTRY_CAPACITY + 1;
// Mapping of fields needed for identifying libaddressinput fields that
// considered required in Autofill.
constexpr auto kRequiredFieldMapping =
base::MakeFixedFlatMap<FieldType, RequiredFieldsForAddressImport>(
{{FieldType::ADDRESS_HOME_STATE,
RequiredFieldsForAddressImport::ADDRESS_REQUIRES_STATE},
{FieldType::ADDRESS_HOME_CITY,
RequiredFieldsForAddressImport::ADDRESS_REQUIRES_CITY},
{FieldType::ADDRESS_HOME_STREET_ADDRESS,
RequiredFieldsForAddressImport::ADDRESS_REQUIRES_LINE1},
{FieldType::ADDRESS_HOME_ZIP,
RequiredFieldsForAddressImport::ADDRESS_REQUIRES_ZIP}});
} // namespace
AutofillCountry::AutofillCountry(const std::string& country_code,
const std::optional<std::string>& locale) {
CountryDataMap* country_data_map = CountryDataMap::GetInstance();
// If the country code is an alias (e.g. "GB" for "UK") expand the country
// code.
country_code_ = country_data_map->HasCountryCodeAlias(country_code)
? country_data_map->GetCountryCodeForAlias(country_code)
: country_code;
required_fields_for_address_import_ =
CountryDataMap::GetInstance()->GetRequiredFieldsForAddressImport(
country_code_);
// Translate the country name by the supplied local.
if (locale)
name_ = l10n_util::GetDisplayNameForCountry(country_code_, *locale);
}
AutofillCountry::~AutofillCountry() = default;
// static
const std::string AutofillCountry::CountryCodeForLocale(
const std::string& locale) {
// Add likely subtags to the locale. In particular, add any likely country
// subtags -- e.g. for locales like "ru" that only include the language.
std::string likely_locale;
UErrorCode error_ignored = U_ZERO_ERROR;
uloc_addLikelySubtags(locale.c_str(),
base::WriteInto(&likely_locale, kLocaleCapacity),
kLocaleCapacity, &error_ignored);
// Extract the country code.
std::string country_code = icu::Locale(likely_locale.c_str()).getCountry();
// Default to the United States if we have no better guess.
if (!base::Contains(CountryDataMap::GetInstance()->country_codes(),
country_code)) {
return "US";
}
return country_code;
}
// static
const AddressCountryCode AutofillCountry::GetDefaultCountryCodeForNewAddress(
const GeoIpCountryCode& geo_ip_country_code,
const std::string& locale) {
// Capitalize the country code, because some APIs might not allow the usage of
// lowercase country codes.
return AddressCountryCode(
base::ToUpperASCII(geo_ip_country_code.value().empty()
? AutofillCountry::CountryCodeForLocale(locale)
: geo_ip_country_code.value()));
}
AutofillCountry::AutofillCountry(const std::string& country_code,
const std::u16string& name,
const std::u16string& postal_code_label,
const std::u16string& state_label)
: country_code_(country_code), name_(name) {}
// Prints a formatted log of a |AutofillCountry| to a |LogBuffer|.
LogBuffer& operator<<(LogBuffer& buffer, const AutofillCountry& country) {
buffer << LogMessage::kImportAddressProfileFromFormAddressRequirements;
buffer << Tag{"div"} << Attrib{"class", "country_data"};
buffer << Tag{"table"};
buffer << Tr{} << "Country code:" << country.country_code();
buffer << Tr{} << "Country name:" << country.name();
buffer << Tr{} << "State required:" << country.requires_state();
buffer << Tr{} << "Zip required:" << country.requires_zip();
buffer << Tr{} << "City required:" << country.requires_city();
buffer << CTag{"table"};
buffer << CTag{"div"};
buffer << CTag{};
return buffer;
}
base::span<const AutofillCountry::AddressFormatExtension>
AutofillCountry::address_format_extensions() const {
// TODO(crbug.com/40216312): Extend more countries. FR and GB already have
// overwrites, because libaddressinput already provides string literals.
static constexpr std::array<AddressFormatExtension, 2> fr_extensions{
{{.type = FieldType::ADDRESS_HOME_STATE,
.label_id = IDS_LIBADDRESSINPUT_PROVINCE,
.placed_after = FieldType::ADDRESS_HOME_CITY,
.separator_before_label = "\n",
.large_sized = true},
{.type = FieldType::ADDRESS_HOME_DEPENDENT_LOCALITY,
.label_id = IDS_AUTOFILL_ADDRESS_EDIT_DIALOG_FRENCH_LOCALITY_2,
.placed_after = FieldType::ADDRESS_HOME_STREET_ADDRESS,
.separator_before_label = "\n",
.large_sized = true}}};
static constexpr std::array<AddressFormatExtension, 1> gb_extensions{
{{.type = FieldType::ADDRESS_HOME_STATE,
.label_id = IDS_LIBADDRESSINPUT_COUNTY,
.placed_after = FieldType::ADDRESS_HOME_ZIP,
.separator_before_label = "\n",
.large_sized = true}}};
static constexpr std::array<AddressFormatExtension, 1> mx_extensions{
{{.type = FieldType::ADDRESS_HOME_ADMIN_LEVEL2,
.label_id = IDS_AUTOFILL_ADDRESS_EDIT_DIALOG_HISPANIC_MUNICIPIO,
.placed_after = FieldType::ADDRESS_HOME_DEPENDENT_LOCALITY,
.separator_before_label = "\n",
.large_sized = true}}};
static constexpr std::array<AddressFormatExtension, 1> de_extensions{
{{.type = FieldType::ADDRESS_HOME_STATE,
.label_id = IDS_LIBADDRESSINPUT_STATE,
.placed_after = FieldType::ADDRESS_HOME_CITY,
.separator_before_label = " "}}};
static constexpr std::array<AddressFormatExtension, 1> pl_extensions{
{{.type = FieldType::ADDRESS_HOME_STATE,
.label_id = IDS_LIBADDRESSINPUT_STATE,
.placed_after = FieldType::ADDRESS_HOME_CITY,
.separator_before_label = " "}}};
static constexpr std::array<AddressFormatExtension, 1> jp_extensions{
{{.type = FieldType::ALTERNATIVE_FULL_NAME,
.label_id = IDS_AUTOFILL_ADDRESS_EDIT_DIALOG_JAPANESE_ALTERNATIVE_NAME,
.placed_after = FieldType::NAME_FULL,
.separator_before_label = "\n",
.large_sized = true}}};
std::vector<std::pair<std::string, base::span<const AddressFormatExtension>>>
overrides = {{"GB", gb_extensions}, {"MX", mx_extensions}};
// FR extensions should contain the ADDRESS_HOME_DEPENDENT_LOCALITY field
// only if flag `kAutofillUseFRAddressModel` is enabled.
base::span<const AddressFormatExtension> fr_extensions_span =
base::FeatureList::IsEnabled(features::kAutofillUseFRAddressModel)
? fr_extensions
: base::span(fr_extensions).first(1u); // first<1>() => type mismatch
overrides.emplace_back("FR", fr_extensions_span);
overrides.emplace_back("DE", de_extensions);
overrides.emplace_back("PL", pl_extensions);
if (base::FeatureList::IsEnabled(
features::kAutofillSupportPhoneticNameForJP)) {
overrides.emplace_back("JP", jp_extensions);
}
auto extensions =
base::flat_map<std::string, base::span<const AddressFormatExtension>>(
std::move(overrides));
auto it = extensions.find(country_code_);
if (it != extensions.end())
return it->second;
return {};
}
bool AutofillCountry::IsAddressFieldSettingAccessible(
FieldType field_type) const {
::i18n::addressinput::AddressField libaddressinput_field;
bool is_valid_field = i18n::FieldForType(field_type, &libaddressinput_field);
// Check if `field_type` is part of libaddressinput's native address format
// or part of the Autofill's address extensions.
return (is_valid_field && ::i18n::addressinput::IsFieldUsed(
libaddressinput_field, country_code_)) ||
base::Contains(
address_format_extensions(), field_type,
[](const AddressFormatExtension& rule) { return rule.type; });
}
bool AutofillCountry::IsAddressFieldRequired(FieldType field_type) const {
auto mapping_it = kRequiredFieldMapping.find(field_type);
return mapping_it != kRequiredFieldMapping.end() &&
(required_fields_for_address_import_ & mapping_it->second);
}
} // namespace autofill
|