File: autofill_country.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (218 lines) | stat: -rw-r--r-- 9,508 bytes parent folder | download | duplicates (2)
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