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())); |
} |