1 // 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/data_model/address.h"
6 
7 #include <stddef.h>
8 #include <algorithm>
9 
10 #include "base/check_op.h"
11 #include "base/feature_list.h"
12 #include "base/i18n/case_conversion.h"
13 #include "base/notreached.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "components/autofill/core/browser/autofill_data_util.h"
19 #include "components/autofill/core/browser/autofill_field.h"
20 #include "components/autofill/core/browser/autofill_type.h"
21 #include "components/autofill/core/browser/data_model/autofill_profile.h"
22 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
23 #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
24 #include "components/autofill/core/browser/geo/autofill_country.h"
25 #include "components/autofill/core/browser/geo/country_names.h"
26 #include "components/autofill/core/browser/geo/state_names.h"
27 #include "components/autofill/core/common/autofill_features.h"
28 #include "components/autofill/core/common/autofill_l10n_util.h"
29 
30 namespace autofill {
31 
32 using structured_address::VerificationStatus;
33 
34 Address::Address() = default;
35 
36 Address::Address(const Address& address) = default;
37 
38 Address::~Address() = default;
39 
40 Address& Address::operator=(const Address& address) = default;
41 
operator ==(const Address & other) const42 bool Address::operator==(const Address& other) const {
43   if (this == &other)
44     return true;
45   // TODO(crbug.com/1130194): Clean legacy implementation once structured
46   // addresses are fully launched.
47   if (structured_address::StructuredAddressesEnabled()) {
48     return structured_address_ == other.structured_address_;
49   }
50 
51   return street_address_ == other.street_address_ &&
52          dependent_locality_ == other.dependent_locality_ &&
53          city_ == other.city_ && state_ == other.state_ &&
54          zip_code_ == other.zip_code_ && sorting_code_ == other.sorting_code_ &&
55          country_code_ == other.country_code_ &&
56          street_name_ == other.street_name_ &&
57          dependent_street_name_ == other.dependent_street_name_ &&
58          house_number_ == other.house_number_ &&
59          premise_name_ == other.premise_name_ &&
60          subpremise_ == other.subpremise_;
61 }
62 
FinalizeAfterImport(bool profile_is_verified)63 bool Address::FinalizeAfterImport(bool profile_is_verified) {
64   // TODO(crbug.com/1130194): Remove feature check once structured addresses are
65   // fully launched.
66   if (structured_address::StructuredAddressesEnabled()) {
67     structured_address_.MigrateLegacyStructure(profile_is_verified);
68     bool result = structured_address_.CompleteFullTree();
69     // If the address could not be completed, it is possible that it contains an
70     // invalid structure.
71     if (!result) {
72       if (structured_address_.WipeInvalidStructure()) {
73         // If the structure was wiped because it is invalid, try to complete the
74         // address again.
75         result = structured_address_.CompleteFullTree();
76       }
77     }
78     return result;
79   }
80   return true;
81 }
82 
MergeStructuredAddress(const Address & newer,bool newer_was_more_recently_used)83 bool Address::MergeStructuredAddress(const Address& newer,
84                                      bool newer_was_more_recently_used) {
85   return structured_address_.MergeWithComponent(newer.GetStructuredAddress(),
86                                                 newer_was_more_recently_used);
87 }
88 
IsStructuredAddressMergeable(const Address & newer) const89 bool Address::IsStructuredAddressMergeable(const Address& newer) const {
90   return structured_address_.IsMergeableWithComponent(
91       newer.GetStructuredAddress());
92 }
93 
GetStructuredAddress() const94 const structured_address::Address& Address::GetStructuredAddress() const {
95   return structured_address_;
96 }
97 
GetRawInfo(ServerFieldType type) const98 base::string16 Address::GetRawInfo(ServerFieldType type) const {
99   DCHECK_EQ(ADDRESS_HOME, AutofillType(type).group());
100 
101   // For structured addresses, the value can be directly retrieved.
102   if (structured_address::StructuredAddressesEnabled())
103     return structured_address_.GetValueForType(type);
104 
105   switch (type) {
106     case ADDRESS_HOME_LINE1:
107       return street_address_.size() > 0 ? street_address_[0] : base::string16();
108 
109     case ADDRESS_HOME_LINE2:
110       return street_address_.size() > 1 ? street_address_[1] : base::string16();
111 
112     case ADDRESS_HOME_LINE3:
113       return street_address_.size() > 2 ? street_address_[2] : base::string16();
114 
115     case ADDRESS_HOME_DEPENDENT_LOCALITY:
116       return dependent_locality_;
117 
118     case ADDRESS_HOME_CITY:
119       return city_;
120 
121     case ADDRESS_HOME_STATE:
122       return state_;
123 
124     case ADDRESS_HOME_ZIP:
125       return zip_code_;
126 
127     case ADDRESS_HOME_SORTING_CODE:
128       return sorting_code_;
129 
130     case ADDRESS_HOME_COUNTRY:
131       return base::ASCIIToUTF16(country_code_);
132 
133     case ADDRESS_HOME_STREET_ADDRESS:
134       return base::JoinString(street_address_, base::ASCIIToUTF16("\n"));
135 
136     case ADDRESS_HOME_APT_NUM:
137       return base::string16();
138 
139     // The following tokens are used for creating new type votes but should not
140     // be filled into fields.
141     case ADDRESS_HOME_STREET_NAME:
142       return street_name_;
143 
144     case ADDRESS_HOME_HOUSE_NUMBER:
145       return house_number_;
146 
147     case ADDRESS_HOME_DEPENDENT_STREET_NAME:
148       return dependent_street_name_;
149 
150     case ADDRESS_HOME_PREMISE_NAME:
151       return premise_name_;
152 
153     case ADDRESS_HOME_SUBPREMISE:
154       return subpremise_;
155 
156     default:
157       NOTREACHED() << "Unrecognized type: " << type;
158       return base::string16();
159   }
160 }
161 
SetRawInfoWithVerificationStatus(ServerFieldType type,const base::string16 & value,VerificationStatus status)162 void Address::SetRawInfoWithVerificationStatus(ServerFieldType type,
163                                                const base::string16& value,
164                                                VerificationStatus status) {
165   DCHECK_EQ(ADDRESS_HOME, AutofillType(type).group());
166 
167   // For structured addresses, the value can directly be set.
168   // TODO(crbug.com/1130194): Clean legacy implementation once structured
169   // addresses are fully launched.
170   if (structured_address::StructuredAddressesEnabled()) {
171     // The street address has a structure that may have already been set before
172     // using the settings dialog. In case the settings dialog was used to change
173     // the address to contain different tokens, the structure must be reset.
174     if (type == ADDRESS_HOME_STREET_ADDRESS) {
175       const base::string16 current_value =
176           structured_address_.GetValueForType(type);
177       if (!current_value.empty()) {
178         bool token_equivalent = structured_address::AreStringTokenEquivalent(
179             value, structured_address_.GetValueForType(type));
180         structured_address_.SetValueForTypeIfPossible(
181             ADDRESS_HOME_STREET_ADDRESS, value, status,
182             /*invalidate_child_nodes=*/!token_equivalent);
183         return;
184       }
185     }
186 
187     structured_address_.SetValueForTypeIfPossible(type, value, status);
188     return;
189   }
190 
191   switch (type) {
192       // If any of the address lines change, the structured tokens must be
193       // reset.
194     case ADDRESS_HOME_LINE1:
195       if (street_address_.empty())
196         street_address_.resize(1);
197       if (street_address_[0] != value)
198         ResetStructuredTokes();
199       street_address_[0] = value;
200       TrimStreetAddress();
201       break;
202 
203     case ADDRESS_HOME_LINE2:
204       if (street_address_.size() < 2)
205         street_address_.resize(2);
206       if (street_address_[1] != value)
207         ResetStructuredTokes();
208       street_address_[1] = value;
209       TrimStreetAddress();
210       break;
211 
212     case ADDRESS_HOME_LINE3:
213       if (street_address_.size() < 3)
214         street_address_.resize(3);
215       if (street_address_[2] != value)
216         ResetStructuredTokes();
217       street_address_[2] = value;
218       TrimStreetAddress();
219       break;
220 
221     case ADDRESS_HOME_DEPENDENT_LOCALITY:
222       dependent_locality_ = value;
223       break;
224 
225     case ADDRESS_HOME_CITY:
226       city_ = value;
227       break;
228 
229     case ADDRESS_HOME_STATE:
230       state_ = value;
231       break;
232 
233     case ADDRESS_HOME_COUNTRY:
234       DCHECK(value.empty() ||
235              data_util::IsValidCountryCode(base::i18n::ToUpper(value)));
236       country_code_ = base::ToUpperASCII(base::UTF16ToASCII(value));
237       break;
238 
239     case ADDRESS_HOME_ZIP:
240       zip_code_ = value;
241       break;
242 
243     case ADDRESS_HOME_SORTING_CODE:
244       sorting_code_ = value;
245       break;
246 
247     case ADDRESS_HOME_STREET_ADDRESS:
248       // If the street address changes, the structured tokens must be reset.
249       if (base::SplitString(value, base::ASCIIToUTF16("\n"),
250                             base::TRIM_WHITESPACE,
251                             base::SPLIT_WANT_ALL) != street_address_) {
252         ResetStructuredTokes();
253         street_address_ =
254             base::SplitString(value, base::ASCIIToUTF16("\n"),
255                               base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
256       }
257       break;
258 
259     // The following types are used to create type votes but should not be
260     // filled into fields.
261     case ADDRESS_HOME_STREET_NAME:
262       street_name_ = value;
263       break;
264 
265     case ADDRESS_HOME_DEPENDENT_STREET_NAME:
266       dependent_street_name_ = value;
267       break;
268 
269     case ADDRESS_HOME_HOUSE_NUMBER:
270       house_number_ = value;
271       break;
272 
273     case ADDRESS_HOME_PREMISE_NAME:
274       premise_name_ = value;
275       break;
276 
277     case ADDRESS_HOME_SUBPREMISE:
278       subpremise_ = value;
279       break;
280 
281     default:
282       NOTREACHED();
283   }
284 }
285 
ResetStructuredTokes()286 void Address::ResetStructuredTokes() {
287   street_name_.clear();
288   dependent_street_name_.clear();
289   house_number_.clear();
290   premise_name_.clear();
291   subpremise_.clear();
292 }
293 
GetMatchingTypes(const base::string16 & text,const std::string & app_locale,ServerFieldTypeSet * matching_types) const294 void Address::GetMatchingTypes(const base::string16& text,
295                                const std::string& app_locale,
296                                ServerFieldTypeSet* matching_types) const {
297   FormGroup::GetMatchingTypes(text, app_locale, matching_types);
298 
299   // Get the country code stored in the profile either from the structured
300   // address if enabled or from the legacy field.
301   // TODO(crbug.com/1130194): Clean legacy implementation once structured
302   // addresses are fully launched.
303   std::string country_code =
304       structured_address::StructuredAddressesEnabled()
305           ? base::UTF16ToUTF8(
306                 structured_address_.GetValueForType(ADDRESS_HOME_COUNTRY))
307           : country_code_;
308 
309   // Check to see if the |text| canonicalized as a country name is a match.
310   std::string entered_country_code =
311       CountryNames::GetInstance()->GetCountryCodeForLocalizedCountryName(
312           text, app_locale);
313   if (!entered_country_code.empty() && country_code == entered_country_code)
314     matching_types->insert(ADDRESS_HOME_COUNTRY);
315 
316   AutofillProfileComparator comparator(app_locale);
317   // Check to see if the |text| could be the full name or abbreviation of a
318   // state.
319   base::string16 canon_text = comparator.NormalizeForComparison(text);
320   base::string16 state_name;
321   base::string16 state_abbreviation;
322   state_names::GetNameAndAbbreviation(canon_text, &state_name,
323                                       &state_abbreviation);
324   if (!state_name.empty() || !state_abbreviation.empty()) {
325     l10n::CaseInsensitiveCompare compare;
326     base::string16 canon_profile_state = comparator.NormalizeForComparison(
327         GetInfo(AutofillType(ADDRESS_HOME_STATE), app_locale));
328     if ((!state_name.empty() &&
329          compare.StringsEqual(state_name, canon_profile_state)) ||
330         (!state_abbreviation.empty() &&
331          compare.StringsEqual(state_abbreviation, canon_profile_state))) {
332       matching_types->insert(ADDRESS_HOME_STATE);
333     }
334   }
335 }
336 
GetSupportedTypes(ServerFieldTypeSet * supported_types) const337 void Address::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
338   supported_types->insert(ADDRESS_HOME_LINE1);
339   supported_types->insert(ADDRESS_HOME_LINE2);
340   supported_types->insert(ADDRESS_HOME_LINE3);
341   supported_types->insert(ADDRESS_HOME_STREET_ADDRESS);
342   supported_types->insert(ADDRESS_HOME_DEPENDENT_LOCALITY);
343   supported_types->insert(ADDRESS_HOME_CITY);
344   supported_types->insert(ADDRESS_HOME_STATE);
345   supported_types->insert(ADDRESS_HOME_ZIP);
346   supported_types->insert(ADDRESS_HOME_SORTING_CODE);
347   supported_types->insert(ADDRESS_HOME_COUNTRY);
348   // If those types are not added, no votes will be generated.
349   if (base::FeatureList::IsEnabled(
350           features::kAutofillAddressEnhancementVotes) ||
351       structured_address::StructuredAddressesEnabled()) {
352     supported_types->insert(ADDRESS_HOME_STREET_NAME);
353     supported_types->insert(ADDRESS_HOME_DEPENDENT_STREET_NAME);
354     supported_types->insert(ADDRESS_HOME_HOUSE_NUMBER);
355     supported_types->insert(ADDRESS_HOME_PREMISE_NAME);
356     supported_types->insert(ADDRESS_HOME_SUBPREMISE);
357   }
358 }
359 
GetInfoImpl(const AutofillType & type,const std::string & locale) const360 base::string16 Address::GetInfoImpl(const AutofillType& type,
361                                     const std::string& locale) const {
362   // Get the country code stored in the profile either from the structured
363   // address if enabled or from the legacy field.
364   // TODO(crbug.com/1130194): Clean legacy implementation once structured
365   // addresses are fully launched.
366   std::string country_code =
367       structured_address::StructuredAddressesEnabled()
368           ? base::UTF16ToUTF8(
369                 structured_address_.GetValueForType(ADDRESS_HOME_COUNTRY))
370           : country_code_;
371 
372   if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
373     return base::ASCIIToUTF16(country_code);
374   }
375 
376   ServerFieldType storable_type = type.GetStorableType();
377   if (storable_type == ADDRESS_HOME_COUNTRY && !country_code.empty())
378     return AutofillCountry(country_code, locale).name();
379 
380   return GetRawInfo(storable_type);
381 }
382 
SetInfoWithVerificationStatusImpl(const AutofillType & type,const base::string16 & value,const std::string & locale,VerificationStatus status)383 bool Address::SetInfoWithVerificationStatusImpl(const AutofillType& type,
384                                                 const base::string16& value,
385                                                 const std::string& locale,
386                                                 VerificationStatus status) {
387   // TODO(crbug.com/1130194): Clean legacy implementation once structured
388   // addresses are fully launched.
389   bool use_structured_address =
390       structured_address::StructuredAddressesEnabled();
391 
392   if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
393     std::string country_code = base::ToUpperASCII(base::UTF16ToASCII(value));
394     if (!data_util::IsValidCountryCode(country_code)) {
395       // To counteract the misuse of autocomplete=country attribute when used
396       // with full country names, if the supplied country code is not a valid,
397       // it is tested if a country code can be derived from the value when it is
398       // interpreted as a full country name. Otherwise an empty string is
399       // assigned to |country_code|.
400       CountryNames* country_names =
401           !value.empty() ? CountryNames::GetInstance() : nullptr;
402       country_code = country_names
403                          ? country_names->GetCountryCodeForLocalizedCountryName(
404                                value, locale)
405                          : std::string();
406     }
407 
408     // TODO(crbug.com/1130194): Clean legacy implementation once structured
409     // addresses are fully launched.
410     if (use_structured_address) {
411       structured_address_.SetValueForTypeIfPossible(ADDRESS_HOME_COUNTRY,
412                                                     country_code, status);
413     } else {
414       country_code_ = country_code;
415     }
416     return !country_code.empty();
417   }
418 
419   if (type.html_type() == HTML_TYPE_FULL_ADDRESS) {
420     // Parsing a full address is too hard.
421     return false;
422   }
423 
424   ServerFieldType storable_type = type.GetStorableType();
425   if (storable_type == ADDRESS_HOME_COUNTRY && !value.empty()) {
426     std::string country_code =
427         CountryNames::GetInstance()->GetCountryCodeForLocalizedCountryName(
428             value, locale);
429     // TODO(crbug.com/1130194): Clean legacy implementation once structured
430     // addresses are fully launched.
431     if (use_structured_address) {
432       structured_address_.SetValueForTypeIfPossible(ADDRESS_HOME_COUNTRY,
433                                                     country_code, status);
434     } else {
435       country_code_ = country_code;
436     }
437     return !country_code_.empty();
438   }
439 
440   SetRawInfoWithVerificationStatus(storable_type, value, status);
441 
442   // Give up when importing addresses with any entirely blank lines.
443   // There's a good chance that this formatting is not intentional, but it's
444   // also not obviously safe to just strip the newlines.
445   if (storable_type == ADDRESS_HOME_STREET_ADDRESS) {
446     // TODO(crbug.com/1130194): Clean legacy implementation once structured
447     // addresses are fully launched.
448     if (structured_address::StructuredAddressesEnabled()) {
449       return structured_address_.IsValueForTypeValid(
450           ADDRESS_HOME_STREET_ADDRESS, /*wipe_if_not=*/true);
451     } else if (base::Contains(street_address_, base::string16())) {
452       street_address_.clear();
453       return false;
454     }
455   }
456 
457   return true;
458 }
459 
GetVerificationStatusImpl(ServerFieldType type) const460 VerificationStatus Address::GetVerificationStatusImpl(
461     ServerFieldType type) const {
462   // TODO(crbug.com/1130194): Clean legacy implementation once structured
463   // addresses are fully launched.
464   if (structured_address::StructuredAddressesEnabled())
465     return structured_address_.GetVerificationStatusForType(type);
466   return VerificationStatus::kNoStatus;
467 }
468 
TrimStreetAddress()469 void Address::TrimStreetAddress() {
470   while (!street_address_.empty() && street_address_.back().empty()) {
471     street_address_.pop_back();
472   }
473 }
474 
475 }  // namespace autofill
476