| Index: chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
|
| diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
|
| index 7f0e8941757553fee005973c409b04247162ea92..f86e335d0d79d3c38abde3735daebfaf807cadce 100644
|
| --- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
|
| +++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
|
| @@ -9,17 +9,20 @@
|
| #include <utility>
|
| #include <vector>
|
|
|
| +#include "base/bind.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/strings/string16.h"
|
| #include "base/strings/stringprintf.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/time/time.h"
|
| #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h"
|
| +#include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
|
| #include "chrome/browser/ui/views/payments/payment_request_views_util.h"
|
| #include "chrome/browser/ui/views/payments/preselected_combobox_model.h"
|
| #include "chrome/browser/ui/views/payments/validating_combobox.h"
|
| #include "chrome/browser/ui/views/payments/validating_textfield.h"
|
| #include "chrome/grit/generated_resources.h"
|
| +#include "components/autofill/core/browser/address_combobox_model.h"
|
| #include "components/autofill/core/browser/autofill_data_util.h"
|
| #include "components/autofill/core/browser/autofill_type.h"
|
| #include "components/autofill/core/browser/credit_card.h"
|
| @@ -33,10 +36,12 @@
|
| #include "components/strings/grit/components_strings.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| #include "ui/native_theme/native_theme.h"
|
| +#include "ui/views/controls/button/md_text_button.h"
|
| #include "ui/views/controls/image_view.h"
|
| #include "ui/views/controls/label.h"
|
| #include "ui/views/controls/textfield/textfield.h"
|
| #include "ui/views/layout/box_layout.h"
|
| +#include "ui/views/layout/grid_layout.h"
|
| #include "ui/views/view.h"
|
|
|
| namespace payments {
|
| @@ -47,6 +52,10 @@ namespace {
|
| // year dropdown.
|
| const int kNumberOfExpirationYears = 10;
|
|
|
| +// This is not quite right but is the closest server type that wasn't already
|
| +// used.
|
| +const auto kBillingAddressType = autofill::ADDRESS_BILLING_LINE1;
|
| +
|
| // Returns the items that are in the expiration month dropdown. Will return the
|
| // months in order starting at "01" until "12". Uses a clock so that the
|
| // |default_index| is set to the current month.
|
| @@ -83,13 +92,16 @@ CreditCardEditorViewController::CreditCardEditorViewController(
|
| PaymentRequestSpec* spec,
|
| PaymentRequestState* state,
|
| PaymentRequestDialogView* dialog,
|
| + BackNavigationType back_navigation,
|
| + int next_ui_tag,
|
| base::OnceClosure on_edited,
|
| base::OnceCallback<void(const autofill::CreditCard&)> on_added,
|
| autofill::CreditCard* credit_card)
|
| - : EditorViewController(spec, state, dialog),
|
| + : EditorViewController(spec, state, dialog, back_navigation),
|
| on_edited_(std::move(on_edited)),
|
| on_added_(std::move(on_added)),
|
| - credit_card_to_edit_(credit_card) {}
|
| + credit_card_to_edit_(credit_card),
|
| + add_billing_address_button_tag_(next_ui_tag) {}
|
|
|
| CreditCardEditorViewController::~CreditCardEditorViewController() {}
|
|
|
| @@ -148,6 +160,80 @@ CreditCardEditorViewController::CreateHeaderView() {
|
| return view;
|
| }
|
|
|
| +// Creates the "Billing Address" custom field view.
|
| +// +------------------------------------+
|
| +// Label* | | Combobox | | Add button | |
|
| +// +------------------------------------+
|
| +std::unique_ptr<views::View>
|
| +CreditCardEditorViewController::CreateCustomFieldView(
|
| + autofill::ServerFieldType type) {
|
| + if (type != kBillingAddressType)
|
| + return std::unique_ptr<views::View>();
|
| + std::unique_ptr<views::View> view = base::MakeUnique<views::View>();
|
| +
|
| + std::unique_ptr<views::GridLayout> layout =
|
| + base::MakeUnique<views::GridLayout>(view.get());
|
| +
|
| + // Combobox column.
|
| + views::ColumnSet* columns = layout->AddColumnSet(0);
|
| + columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 0,
|
| + views::GridLayout::FIXED, kMaximumLabelWidth, 0);
|
| +
|
| + // This is the horizontal padding between the combobox and the add button.
|
| + constexpr int kComboboxAddButtonHorizontalPadding = 8;
|
| + columns->AddPaddingColumn(0, kComboboxAddButtonHorizontalPadding);
|
| +
|
| + columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
|
| + views::GridLayout::USE_PREF, 0, 0);
|
| +
|
| + layout->StartRow(0, 0);
|
| +
|
| + EditorField billing_address_field(
|
| + kBillingAddressType,
|
| + l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_BILLING_ADDRESS),
|
| + EditorField::LengthHint::HINT_SHORT, /*required=*/true,
|
| + EditorField::ControlType::COMBOBOX);
|
| +
|
| + // The combobox filled with potential billing addresses.
|
| + std::unique_ptr<autofill::AddressComboboxModel> address_combobox_model =
|
| + base::MakeUnique<autofill::AddressComboboxModel>(
|
| + *state()->GetPersonalDataManager(), state()->GetApplicationLocale());
|
| + int selected_index = -1;
|
| + if (credit_card_to_edit_ &&
|
| + !credit_card_to_edit_->billing_address_id().empty()) {
|
| + selected_index = address_combobox_model->GetIndexOfIdentifier(
|
| + credit_card_to_edit_->billing_address_id());
|
| + }
|
| + // This takes care of rare cases where the the billing address set on the
|
| + // current card isn't valid anymore.
|
| + if (selected_index == -1)
|
| + selected_index = address_combobox_model->GetDefaultIndex();
|
| +
|
| + ValidatingCombobox* combobox =
|
| + new ValidatingCombobox(std::move(address_combobox_model),
|
| + CreateValidationDelegate(billing_address_field));
|
| + combobox->SetSelectedIndex(selected_index);
|
| +
|
| + // Using autofill field type as a view ID (for testing).
|
| + combobox->set_id(static_cast<int>(billing_address_field.type));
|
| + combobox->set_listener(this);
|
| +
|
| + // |combobox| will now be owned by |row|.
|
| + layout->AddView(combobox);
|
| +
|
| + // The button to add new billing addresses.
|
| + std::unique_ptr<views::Button> add_button(
|
| + views::MdTextButton::Create(this, l10n_util::GetStringUTF16(IDS_ADD)));
|
| + add_button->set_id(
|
| + static_cast<int>(DialogViewID::ADD_BILLING_ADDRESS_BUTTON));
|
| + add_button->set_tag(add_billing_address_button_tag_);
|
| +
|
| + // |add_button| will now be owned by |row|.
|
| + layout->AddView(add_button.release());
|
| + view->SetLayoutManager(layout.release());
|
| + return view;
|
| +}
|
| +
|
| std::vector<EditorField> CreditCardEditorViewController::GetFieldDefinitions() {
|
| return std::vector<EditorField>{
|
| {autofill::CREDIT_CARD_NUMBER,
|
| @@ -163,7 +249,11 @@ std::vector<EditorField> CreditCardEditorViewController::GetFieldDefinitions() {
|
| {autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR,
|
| l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_YEAR),
|
| EditorField::LengthHint::HINT_SHORT, /* required= */ true,
|
| - EditorField::ControlType::COMBOBOX}};
|
| + EditorField::ControlType::COMBOBOX},
|
| + {kBillingAddressType,
|
| + l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_BILLING_ADDRESS),
|
| + EditorField::LengthHint::HINT_LONG, /* required= */ true,
|
| + EditorField::ControlType::CUSTOMFIELD}};
|
| }
|
|
|
| base::string16 CreditCardEditorViewController::GetInitialValueForType(
|
| @@ -204,8 +294,18 @@ bool CreditCardEditorViewController::ValidateModelAndSave() {
|
| locale);
|
| }
|
|
|
| + views::Combobox* address_combobox =
|
| + static_cast<views::Combobox*>(dialog()->GetViewByID(kBillingAddressType));
|
| + autofill::AddressComboboxModel* model =
|
| + static_cast<autofill::AddressComboboxModel*>(address_combobox->model());
|
| +
|
| + credit_card.set_billing_address_id(
|
| + model->GetItemIdentifierAt(address_combobox->selected_index()));
|
| +
|
| // TODO(crbug.com/711365): Display global error message.
|
| - if (autofill::GetCompletionStatusForCard(credit_card, locale) !=
|
| + if (autofill::GetCompletionStatusForCard(
|
| + credit_card, locale,
|
| + state()->GetPersonalDataManager()->GetProfiles()) !=
|
| autofill::CREDIT_CARD_COMPLETE) {
|
| return false;
|
| }
|
| @@ -215,6 +315,8 @@ bool CreditCardEditorViewController::ValidateModelAndSave() {
|
| state()->GetPersonalDataManager()->AddCreditCard(credit_card);
|
| std::move(on_added_).Run(credit_card);
|
| } else {
|
| + credit_card_to_edit_->set_billing_address_id(
|
| + credit_card.billing_address_id());
|
| // We were in edit mode. Copy the data from the temporary object to retain
|
| // the edited object's other properties (use count, use date, guid, etc.).
|
| for (const auto& field : text_fields()) {
|
| @@ -259,12 +361,11 @@ CreditCardEditorViewController::GetComboboxModelForType(
|
| int default_index = 0;
|
| std::vector<base::string16> months =
|
| GetExpirationMonthItems(&default_index);
|
| - return std::unique_ptr<ui::ComboboxModel>(
|
| - new PreselectedComboboxModel(months, default_index));
|
| + return base::MakeUnique<PreselectedComboboxModel>(months, default_index);
|
| }
|
| case autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR:
|
| - return std::unique_ptr<ui::ComboboxModel>(
|
| - new ui::SimpleComboboxModel(GetExpirationYearItems()));
|
| + return base::MakeUnique<ui::SimpleComboboxModel>(
|
| + GetExpirationYearItems());
|
| default:
|
| NOTREACHED();
|
| break;
|
| @@ -278,12 +379,42 @@ base::string16 CreditCardEditorViewController::GetSheetTitle() {
|
|
|
| // Gets the completion message, or empty if nothing is missing from the card.
|
| base::string16 title = autofill::GetCompletionMessageForCard(
|
| - autofill::GetCompletionStatusForCard(*credit_card_to_edit_,
|
| - state()->GetApplicationLocale()));
|
| + autofill::GetCompletionStatusForCard(
|
| + *credit_card_to_edit_, state()->GetApplicationLocale(),
|
| + state()->GetPersonalDataManager()->GetProfiles()));
|
| return title.empty() ? l10n_util::GetStringUTF16(IDS_PAYMENTS_EDIT_CARD)
|
| : title;
|
| }
|
|
|
| +void CreditCardEditorViewController::ButtonPressed(views::Button* sender,
|
| + const ui::Event& event) {
|
| + if (sender->tag() == add_billing_address_button_tag_) {
|
| + dialog()->ShowShippingAddressEditor(
|
| + BackNavigationType::kOneStep,
|
| + /*on_edited=*/
|
| + base::OnceClosure(),
|
| + /*on_added=*/
|
| + base::BindOnce(
|
| + &CreditCardEditorViewController::AddAndSelectNewBillingAddress,
|
| + base::Unretained(this)),
|
| + /*profile=*/nullptr);
|
| + } else {
|
| + EditorViewController::ButtonPressed(sender, event);
|
| + }
|
| +}
|
| +
|
| +void CreditCardEditorViewController::AddAndSelectNewBillingAddress(
|
| + const autofill::AutofillProfile& profile) {
|
| + views::Combobox* address_combobox =
|
| + static_cast<views::Combobox*>(dialog()->GetViewByID(kBillingAddressType));
|
| + autofill::AddressComboboxModel* model =
|
| + static_cast<autofill::AddressComboboxModel*>(address_combobox->model());
|
| + int index = model->AddNewProfile(profile);
|
| + address_combobox->SetSelectedIndex(index);
|
| + // Force revalidation.
|
| + address_combobox->OnBlur();
|
| +}
|
| +
|
| CreditCardEditorViewController::CreditCardValidationDelegate::
|
| CreditCardValidationDelegate(
|
| const EditorField& field,
|
| @@ -303,6 +434,15 @@ bool CreditCardEditorViewController::CreditCardValidationDelegate::
|
|
|
| bool CreditCardEditorViewController::CreditCardValidationDelegate::
|
| ValidateCombobox(views::Combobox* combobox) {
|
| + // The billing address ID is the selected item identifier and not the combobox
|
| + // value itself.
|
| + if (field_.type == kBillingAddressType) {
|
| + // TODO(crbug.com/718905) Find a way to deal with existing incomplete
|
| + // addresses when choosing them as billing addresses.
|
| + autofill::AddressComboboxModel* model =
|
| + static_cast<autofill::AddressComboboxModel*>(combobox->model());
|
| + return !model->GetItemIdentifierAt(combobox->selected_index()).empty();
|
| + }
|
| return ValidateValue(combobox->GetTextForRow(combobox->selected_index()));
|
| }
|
|
|
|
|