summaryrefslogtreecommitdiff
path: root/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/autofill/core/browser/autofill_profile_validation_util.cc')
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_validation_util.cc371
1 files changed, 0 insertions, 371 deletions
diff --git a/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc b/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc
deleted file mode 100644
index 437fb53d36a..00000000000
--- a/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2017 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/autofill_profile_validation_util.h"
-
-#include <string>
-#include <utility>
-
-#include "base/check.h"
-#include "base/containers/contains.h"
-#include "base/i18n/case_conversion.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/geo/address_i18n.h"
-#include "components/autofill/core/browser/geo/country_data.h"
-#include "components/autofill/core/browser/validation.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
-#include "third_party/libphonenumber/dist/cpp/src/phonenumbers/phonenumberutil.h"
-
-namespace autofill {
-
-namespace {
-
-using ::i18n::addressinput::COUNTRY;
-using ::i18n::addressinput::ADMIN_AREA;
-using ::i18n::addressinput::LOCALITY;
-using ::i18n::addressinput::DEPENDENT_LOCALITY;
-using ::i18n::addressinput::SORTING_CODE;
-using ::i18n::addressinput::POSTAL_CODE;
-using ::i18n::addressinput::STREET_ADDRESS;
-using ::i18n::addressinput::RECIPIENT;
-
-using i18nAddressData = ::i18n::addressinput::AddressData;
-using i18nAddressField = ::i18n::addressinput::AddressField;
-using i18nAddressProblem = ::i18n::addressinput::AddressProblem;
-using i18nFieldProblemMap = ::i18n::addressinput::FieldProblemMap;
-
-using ::i18n::addressinput::INVALID_FORMAT;
-using ::i18n::addressinput::MISMATCHING_VALUE;
-using ::i18n::addressinput::MISSING_REQUIRED_FIELD;
-using ::i18n::addressinput::UNEXPECTED_FIELD;
-using ::i18n::addressinput::UNKNOWN_VALUE;
-using ::i18n::addressinput::UNSUPPORTED_FIELD;
-
-using ::i18n::phonenumbers::PhoneNumberUtil;
-
-const i18nAddressField kFields[] = {COUNTRY, ADMIN_AREA, LOCALITY,
- DEPENDENT_LOCALITY, POSTAL_CODE};
-const i18nAddressProblem kProblems[] = {
- UNEXPECTED_FIELD, MISSING_REQUIRED_FIELD, UNKNOWN_VALUE,
- INVALID_FORMAT, MISMATCHING_VALUE, UNSUPPORTED_FIELD};
-
-// If the |address_field| is valid, set the validity state of the
-// |address_field| in the |profile| to the |state| and return true.
-// Otherwise, return false.
-bool SetValidityStateForAddressField(const AutofillProfile* profile,
- i18nAddressField address_field,
- AutofillDataModel::ValidityState state) {
- ServerFieldType server_field = i18n::TypeForField(address_field,
- /*billing=*/false);
- if (server_field == UNKNOWN_TYPE)
- return false;
- DCHECK(profile);
- profile->SetValidityState(server_field, state, AutofillDataModel::CLIENT);
- return true;
-}
-
-// Set the validity state of all address fields in the |profile| to |state|.
-void SetAllAddressValidityStates(const AutofillProfile* profile,
- AutofillDataModel::ValidityState state) {
- DCHECK(profile);
- for (auto field : kFields)
- SetValidityStateForAddressField(profile, field, state);
-}
-
-// Returns all relevant pairs of (field, problem), where field is in
-// |kFields|, and problem is in |kProblems|.
-i18nFieldProblemMap* CreateFieldProblemMap() {
- i18nFieldProblemMap* filter = new i18nFieldProblemMap();
- for (auto field : kFields) {
- for (auto problem : kProblems) {
- filter->insert(std::make_pair(field, problem));
- }
- }
- return filter;
-}
-
-// GetFilter() will make sure that the validation only returns problems that
-// are relevant.
-const i18nFieldProblemMap* GetFilter() {
- static const i18nFieldProblemMap* const filter = CreateFieldProblemMap();
- return filter;
-}
-
-// Initializes |address| data from the address info in the |profile|.
-void InitializeAddressFromProfile(const AutofillProfile& profile,
- i18nAddressData* address) {
- address->region_code =
- base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
- address->administrative_area =
- base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE));
- address->locality = base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY));
- address->dependent_locality =
- base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
- // The validation is case insensitive, and the postal codes are always upper
- // case.
- address->postal_code = base::UTF16ToUTF8(
- base::i18n::ToUpper(profile.GetRawInfo(ADDRESS_HOME_ZIP)));
-}
-
-void SetEmptyValidityIfEmpty(const AutofillProfile* profile) {
- if (profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty())
- profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY,
- AutofillDataModel::CLIENT);
- if (profile->GetRawInfo(ADDRESS_HOME_STATE).empty())
- profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY,
- AutofillDataModel::CLIENT);
- if (profile->GetRawInfo(ADDRESS_HOME_CITY).empty())
- profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::EMPTY,
- AutofillDataModel::CLIENT);
- if (profile->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY).empty())
- profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
- AutofillDataModel::EMPTY,
- AutofillDataModel::CLIENT);
- if (profile->GetRawInfo(ADDRESS_HOME_ZIP).empty())
- profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY,
- AutofillDataModel::CLIENT);
-}
-
-void SetInvalidIfUnvalidated(const AutofillProfile* profile) {
- if (profile->GetValidityState(ADDRESS_HOME_COUNTRY,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED) {
- profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_STATE,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED) {
- profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED) {
- profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED) {
- profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
- AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED) {
- profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-}
-
-void MaybeApplyValidToFields(const AutofillProfile* profile) {
- // The metadata works from top to bottom. Therefore, a so far UNVALIDATED
- // subregion can only be validated if its super-region is VALID. In this
- // case, it's VALID if it has not been marked as INVALID or EMPTY.
-
- if (profile->GetValidityState(ADDRESS_HOME_STATE,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED) {
- profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::VALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED &&
- profile->GetValidityState(ADDRESS_HOME_STATE,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::VALID) {
- profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::VALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED &&
- profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
- AutofillDataModel::VALID) {
- profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
- AutofillDataModel::VALID,
- AutofillDataModel::CLIENT);
- }
-
- // ZIP only depends on COUNTRY. If it's not so far marked as INVALID or EMPTY,
- // then it's VALID.
- if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) ==
- AutofillDataModel::UNVALIDATED) {
- profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::VALID,
- AutofillDataModel::CLIENT);
- }
-}
-
-void ApplyValidOnlyIfAllChildrenNotInvalid(const AutofillProfile* profile) {
- if (profile->GetValidityState(ADDRESS_HOME_STATE,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::INVALID &&
- profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) ==
- AutofillDataModel::INVALID) {
- profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
- AutofillDataModel::INVALID) {
- profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-
- if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
- AutofillDataModel::CLIENT) ==
- AutofillDataModel::INVALID) {
- profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
- }
-}
-
-} // namespace
-
-namespace profile_validation_util {
-
-void ValidateProfile(const AutofillProfile* profile,
- AddressValidator* address_validator) {
- DCHECK(address_validator);
- DCHECK(profile);
- ValidateAddressStrictly(profile, address_validator);
- ValidatePhoneNumber(profile);
- ValidateEmailAddress(profile);
-}
-
-AddressValidator::Status ValidateAddress(const AutofillProfile* profile,
- AddressValidator* address_validator) {
- DCHECK(address_validator);
- DCHECK(profile);
-
- SetAllAddressValidityStates(profile, AutofillDataModel::UNVALIDATED);
-
- if (!base::Contains(
- CountryDataMap::GetInstance()->country_codes(),
- base::UTF16ToUTF8(profile->GetRawInfo(ADDRESS_HOME_COUNTRY)))) {
- // If the country code is not in the database, the country code and the
- // profile are invalid, and other fields cannot be validated, because it is
- // unclear which, if any, rule should apply.
- SetValidityStateForAddressField(profile, COUNTRY,
- AutofillDataModel::INVALID);
- SetEmptyValidityIfEmpty(profile);
- return AddressValidator::SUCCESS;
- }
-
- // The COUNTRY was already listed in the CountryDataMap, therefore it's valid.
- SetValidityStateForAddressField(profile, COUNTRY, AutofillDataModel::VALID);
-
- i18nAddressData address;
- InitializeAddressFromProfile(*profile, &address);
- i18nFieldProblemMap problems;
- // status denotes if the rule was successfully loaded before validation.
- AddressValidator::Status status =
- address_validator->ValidateAddress(address, GetFilter(), &problems);
-
- // The address fields for which validation is not supported by the metadata
- // will be marked as UNSUPPORTED_FIELDs. These fields should be treated like
- // VALID fields to stay consistent. INVALID_FORMATs, MISMATCHING_VALUEs or
- // UNKNOWN_VALUEs are INVALID. MISSING_REQUIRED_FIELD would be marked as EMPTY
- // along other empty fields. UNEXPECTED_FIELD would mean that there is also no
- // metadata for validation, therefore, they are also UNSUPPORTED_FIELDs, and
- // thus they would be treated as VALID fields.
- for (auto problem : problems) {
- if (problem.second == UNSUPPORTED_FIELD) {
- SetValidityStateForAddressField(profile, problem.first,
- AutofillDataModel::VALID);
-
- } else if (problem.second == INVALID_FORMAT ||
- problem.second == MISMATCHING_VALUE ||
- problem.second == UNKNOWN_VALUE) {
- SetValidityStateForAddressField(profile, problem.first,
- AutofillDataModel::INVALID);
- }
- }
-
- SetEmptyValidityIfEmpty(profile);
-
- // Fields (except COUNTRY) could be VALID, only if the rules were available.
- if (status == AddressValidator::SUCCESS)
- MaybeApplyValidToFields(profile);
-
- return status;
-}
-
-void ValidateAddressStrictly(const AutofillProfile* profile,
- AddressValidator* address_validator) {
- DCHECK(address_validator);
- DCHECK(profile);
-
- // If the rules were loaded successfully, add a second layer of validation:
- // 1. For a field to stay valid after the first run, all the fields that
- // depend on that field for validation need to not be invalid on the first
- // run, otherwise there is a chance that the data on that field was also
- // invalid (incorrect.)
- // Example: 1225 Notre-Dame Ouest, Montreal, Quebec, H3C 2A3, United States.
- // A human validator can see that the country is most probably the invalid
- // field. The first step helps us validate the rules interdependently.
- // 2. All the address fields that could not be validated (UNVALIDATED),
- // should be considered as invalid.
-
- if (ValidateAddress(profile, address_validator) ==
- AddressValidator::SUCCESS) {
- ApplyValidOnlyIfAllChildrenNotInvalid(profile);
- SetInvalidIfUnvalidated(profile);
- }
-}
-
-void ValidateEmailAddress(const AutofillProfile* profile) {
- const std::u16string& email = profile->GetRawInfo(EMAIL_ADDRESS);
- if (email.empty()) {
- profile->SetValidityState(EMAIL_ADDRESS, AutofillDataModel::EMPTY,
- AutofillDataModel::CLIENT);
- return;
- }
-
- profile->SetValidityState(EMAIL_ADDRESS,
- autofill::IsValidEmailAddress(email)
- ? AutofillDataModel::VALID
- : AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
-}
-
-void ValidatePhoneNumber(const AutofillProfile* profile) {
- const std::string& phone_number =
- base::UTF16ToUTF8(profile->GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
- if (phone_number.empty()) {
- profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY,
- AutofillDataModel::CLIENT);
- return;
- }
-
- const std::string& country_code =
- base::UTF16ToUTF8(profile->GetRawInfo(ADDRESS_HOME_COUNTRY));
- if (!base::Contains(CountryDataMap::GetInstance()->country_codes(),
- country_code)) {
- // If the country code is not in the database, the phone number cannot be
- // validated.
- profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER,
- AutofillDataModel::UNVALIDATED,
- AutofillDataModel::CLIENT);
- return;
- }
-
- PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
- profile->SetValidityState(
- PHONE_HOME_WHOLE_NUMBER,
- phone_util->IsPossibleNumberForString(phone_number, country_code)
- ? AutofillDataModel::VALID
- : AutofillDataModel::INVALID,
- AutofillDataModel::CLIENT);
-}
-
-} // namespace profile_validation_util
-} // namespace autofill