| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/autofill/address_editor_controller.h" |
| |
| #include <string> |
| #include <string_view> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/callback_list.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/autofill/personal_data_manager_factory.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/global_features.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "components/application_locale_storage/application_locale_storage.h" |
| #include "components/autofill/core/browser/country_type.h" |
| #include "components/autofill/core/browser/data_manager/addresses/address_data_manager.h" |
| #include "components/autofill/core/browser/data_manager/personal_data_manager.h" |
| #include "components/autofill/core/browser/geo/address_i18n.h" |
| #include "components/autofill/core/browser/geo/autofill_country.h" |
| #include "components/autofill/core/browser/ui/addresses/autofill_address_util.h" |
| #include "components/variations/service/variations_service.h" |
| #include "third_party/libaddressinput/chromium/chrome_metadata_source.h" |
| #include "third_party/libaddressinput/messages.h" |
| #include "ui/base/l10n/l10n_util.h" |
| |
| namespace autofill { |
| |
| AddressEditorController::AddressEditorController( |
| const AutofillProfile& profile_to_edit, |
| PersonalDataManager* pdm, |
| bool is_validatable) |
| : profile_to_edit_(profile_to_edit), |
| pdm_(*pdm), |
| locale_(g_browser_process->GetFeatures() |
| ->application_locale_storage() |
| ->Get()), |
| is_validatable_(is_validatable) { |
| const variations::VariationsService* variations_service = |
| g_browser_process->variations_service(); |
| countries_.SetCountries( |
| GeoIpCountryCode(variations_service |
| ? variations_service->GetLatestCountry() |
| : std::string()), |
| locale_); |
| std::u16string profile_country_code = |
| profile_to_edit_.GetRawInfo(ADDRESS_HOME_COUNTRY); |
| UpdateEditorFields(base::UTF16ToASCII(profile_country_code)); |
| } |
| |
| AddressEditorController::~AddressEditorController() = default; |
| |
| CountryComboboxModel& AddressEditorController::GetCountryComboboxModel() { |
| return countries_; |
| } |
| |
| void AddressEditorController::UpdateEditorFields( |
| const std::string& country_code) { |
| editor_fields_.clear(); |
| |
| std::vector<std::vector<AutofillAddressUIComponent>> components; |
| GetAddressComponents(country_code, locale_, |
| /*include_literals=*/false, &components, |
| &language_code_); |
| profile_to_edit_.set_language_code(language_code_); |
| |
| // Insert the Country combobox at the top. |
| editor_fields_.emplace_back( |
| ADDRESS_HOME_COUNTRY, |
| l10n_util::GetStringUTF16(IDS_LIBADDRESSINPUT_COUNTRY_OR_REGION_LABEL), |
| EditorField::LengthHint::HINT_LONG, /*is_required=*/false, |
| EditorField::ControlType::COMBOBOX); |
| |
| for (const std::vector<AutofillAddressUIComponent>& line : components) { |
| for (const AutofillAddressUIComponent& component : line) { |
| EditorField::LengthHint length_hint = |
| component.length_hint == AutofillAddressUIComponent::HINT_LONG |
| ? EditorField::LengthHint::HINT_LONG |
| : EditorField::LengthHint::HINT_SHORT; |
| EditorField::ControlType control_type = |
| component.field == ADDRESS_HOME_COUNTRY |
| ? EditorField::ControlType::COMBOBOX |
| : EditorField::ControlType::TEXTFIELD; |
| |
| editor_fields_.emplace_back( |
| component.field, base::UTF8ToUTF16(component.name), length_hint, |
| component.is_required, control_type); |
| } |
| } |
| // Always add phone number and email at the end. |
| editor_fields_.emplace_back( |
| PHONE_HOME_WHOLE_NUMBER, |
| l10n_util::GetStringUTF16(IDS_SETTINGS_AUTOFILL_ADDRESSES_PHONE), |
| EditorField::LengthHint::HINT_SHORT, /*is_required=*/false, |
| EditorField::ControlType::TEXTFIELD_NUMBER); |
| |
| editor_fields_.emplace_back( |
| EMAIL_ADDRESS, |
| l10n_util::GetStringUTF16(IDS_SETTINGS_AUTOFILL_ADDRESSES_EMAIL), |
| EditorField::LengthHint::HINT_LONG, /*is_required=*/false, |
| EditorField::ControlType::TEXTFIELD); |
| } |
| |
| void AddressEditorController::SetProfileInfo(FieldType type, |
| const std::u16string& value) { |
| // Since the countries combobox contains the country names, not the country |
| // codes, and hence we should use `SetInfo()` to make sure they get converted |
| // to country codes. Also use `SetInfo()` for `NAME_FULL` so that its |
| // dependent nodes (NAME_FIRST, NAME_LAST, etc) are also updated. This does |
| // not need to be done for addresses because it is handled internally inside |
| // `SetRawInfo()`. |
| if (type == ADDRESS_HOME_COUNTRY || type == NAME_FULL) { |
| profile_to_edit_.SetInfoWithVerificationStatus( |
| type, value, locale_, VerificationStatus::kUserVerified); |
| return; |
| } |
| |
| profile_to_edit_.SetRawInfoWithVerificationStatus( |
| type, value, VerificationStatus::kUserVerified); |
| } |
| |
| std::u16string AddressEditorController::GetProfileInfo(FieldType type) { |
| // TDOD(mamir): Update the implementation to format strings properly. |
| return profile_to_edit_.GetInfo(type, locale_); |
| } |
| |
| const AutofillProfile& AddressEditorController::GetAddressProfile() { |
| return profile_to_edit_; |
| } |
| |
| void AddressEditorController::SetIsValid(bool is_valid) { |
| bool should_notify = is_valid_ != is_valid; |
| is_valid_ = is_valid; |
| if (should_notify) { |
| on_is_valid_change_callbacks_.Notify(is_valid); |
| } |
| } |
| |
| base::CallbackListSubscription |
| AddressEditorController::AddIsValidChangedCallback( |
| OnIsValidChangeCallbackList::CallbackType callback) { |
| return on_is_valid_change_callbacks_.Add(std::move(callback)); |
| } |
| |
| bool AddressEditorController::IsValid(const EditorField& field, |
| std::u16string_view value) { |
| if (is_validatable_ && field.is_required && |
| base::CollapseWhitespace(value, true).empty()) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| } // namespace autofill |