Chromium Code Reviews| 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 3c5535098e64281cb12b0d28bd15078d6f2e05ce..b7e2167705092806724a2a24c7fa2a3c161e69e4 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,9 @@ namespace { |
| // year dropdown. |
| const int kNumberOfExpirationYears = 10; |
| +// To avoid collision with server field types which are used as view IDs. |
| +const auto kBillingAddressType = autofill::MAX_VALID_FIELD_TYPE; |
|
Mathieu
2017/05/04 20:29:19
we could use ADDRESS_BILLING_LINE_1, which is othe
MAD
2017/05/05 00:50:07
Done.
|
| + |
| // 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 +91,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 +159,86 @@ CreditCardEditorViewController::CreateHeaderView() { |
| return view; |
| } |
| +std::unique_ptr<views::View> |
|
Mathieu
2017/05/04 20:29:19
I would add ASCII art about what you are building
MAD
2017/05/05 00:50:07
Done.
|
| +CreditCardEditorViewController::CreateCustomFieldsView() { |
| + std::unique_ptr<views::View> view = base::MakeUnique<views::View>(); |
| + |
| + std::unique_ptr<views::GridLayout> layout = |
| + base::MakeUnique<views::GridLayout>(view.get()); |
| + |
| + // Label column. |
| + views::ColumnSet* columns = layout->AddColumnSet(0); |
| + columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0, |
| + views::GridLayout::USE_PREF, 0, 0); |
| + |
| + // This is the horizontal padding between the label and the combobox. |
| + columns->AddPaddingColumn(0, kLabelInputFieldHorizontalPadding); |
| + |
| + columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0, |
| + views::GridLayout::USE_PREF, 0, 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); |
| + |
| + std::unique_ptr<views::Label> label = base::MakeUnique<views::Label>( |
| + billing_address_field.label + base::ASCIIToUTF16("*")); |
| + |
| + label->SetMultiLine(true); |
| + label->SetMaximumWidth(kMaximumLabelWidth); |
| + layout->AddView(label.release()); |
| + |
| + // The combobox filled with potential billing addresses. |
| + int selected_index = -1; |
|
Mathieu
2017/05/04 20:29:19
nit: I would move this closer to the if block
MAD
2017/05/05 00:50:07
Done.
|
| + std::unique_ptr<autofill::AddressComboboxModel> address_combobox_model( |
|
Mathieu
2017/05/04 20:29:18
can use = here?
MAD
2017/05/05 00:50:07
OK, but I thought that constructor were prefered i
|
| + base::MakeUnique<autofill::AddressComboboxModel>( |
| + *state()->GetPersonalDataManager(), state()->GetApplicationLocale())); |
| + 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, |
| @@ -204,8 +295,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 +316,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 +362,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 +380,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(), |
|
Mathieu
2017/05/04 20:29:19
TODO: there is a possibility that the billing addr
MAD
2017/05/05 00:50:07
Really? Should't the editor prevent the creation o
Mathieu
2017/05/05 13:51:33
We may have an incomplete billing address because
MAD
2017/05/05 18:32:33
HA OK! Got it... Added a TODO and a bug.
|
| + /*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 +435,12 @@ bool CreditCardEditorViewController::CreditCardValidationDelegate:: |
| bool CreditCardEditorViewController::CreditCardValidationDelegate:: |
| ValidateCombobox(views::Combobox* combobox) { |
| + // The address combobox value only need to not be an empty item identifier. |
|
Mathieu
2017/05/04 20:29:19
rephrase/fix?
MAD
2017/05/05 00:50:07
Done.
|
| + if (field_.type == kBillingAddressType) { |
| + autofill::AddressComboboxModel* model = |
| + static_cast<autofill::AddressComboboxModel*>(combobox->model()); |
| + return !model->GetItemIdentifierAt(combobox->selected_index()).empty(); |
| + } |
| return ValidateValue(combobox->GetTextForRow(combobox->selected_index())); |
| } |