OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/payments/credit_card_editor_view_controller.h" | 5 #include "chrome/browser/ui/views/payments/credit_card_editor_view_controller.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "components/payments/content/payment_request_spec.h" | 34 #include "components/payments/content/payment_request_spec.h" |
35 #include "components/payments/content/payment_request_state.h" | 35 #include "components/payments/content/payment_request_state.h" |
36 #include "components/strings/grit/components_strings.h" | 36 #include "components/strings/grit/components_strings.h" |
37 #include "ui/base/l10n/l10n_util.h" | 37 #include "ui/base/l10n/l10n_util.h" |
38 #include "ui/native_theme/native_theme.h" | 38 #include "ui/native_theme/native_theme.h" |
39 #include "ui/views/controls/button/md_text_button.h" | 39 #include "ui/views/controls/button/md_text_button.h" |
40 #include "ui/views/controls/image_view.h" | 40 #include "ui/views/controls/image_view.h" |
41 #include "ui/views/controls/label.h" | 41 #include "ui/views/controls/label.h" |
42 #include "ui/views/controls/textfield/textfield.h" | 42 #include "ui/views/controls/textfield/textfield.h" |
43 #include "ui/views/layout/box_layout.h" | 43 #include "ui/views/layout/box_layout.h" |
| 44 #include "ui/views/layout/fill_layout.h" |
44 #include "ui/views/layout/grid_layout.h" | 45 #include "ui/views/layout/grid_layout.h" |
45 #include "ui/views/view.h" | 46 #include "ui/views/view.h" |
46 | 47 |
47 namespace payments { | 48 namespace payments { |
48 | 49 |
49 namespace { | 50 namespace { |
50 | 51 |
51 // Number of years (including the current one) to be shown in the expiration | 52 // Number of years (including the current one) to be shown in the expiration |
52 // year dropdown. | 53 // year dropdown. |
53 const int kNumberOfExpirationYears = 10; | 54 const int kNumberOfExpirationYears = 10; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 // | Cards Accepted | | 112 // | Cards Accepted | |
112 // | | | 113 // | | |
113 // | | VISA | | MC | | AMEX | | | 114 // | | VISA | | MC | | AMEX | | |
114 // +----------------------------------------------+ | 115 // +----------------------------------------------+ |
115 std::unique_ptr<views::View> | 116 std::unique_ptr<views::View> |
116 CreditCardEditorViewController::CreateHeaderView() { | 117 CreditCardEditorViewController::CreateHeaderView() { |
117 std::unique_ptr<views::View> view = base::MakeUnique<views::View>(); | 118 std::unique_ptr<views::View> view = base::MakeUnique<views::View>(); |
118 | 119 |
119 // 9dp is required between the first row (label) and second row (icons). | 120 // 9dp is required between the first row (label) and second row (icons). |
120 constexpr int kRowVerticalSpacing = 9; | 121 constexpr int kRowVerticalSpacing = 9; |
| 122 // 6dp is added to the bottom padding, for a total of 12 between the icons and |
| 123 // the first input field. |
| 124 constexpr int kRowBottomPadding = 6; |
121 views::BoxLayout* layout = new views::BoxLayout( | 125 views::BoxLayout* layout = new views::BoxLayout( |
122 views::BoxLayout::kVertical, payments::kPaymentRequestRowHorizontalInsets, | 126 views::BoxLayout::kVertical, payments::kPaymentRequestRowHorizontalInsets, |
123 0, kRowVerticalSpacing); | 127 kRowBottomPadding, kRowVerticalSpacing); |
124 layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); | 128 layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); |
125 layout->set_cross_axis_alignment( | 129 layout->set_cross_axis_alignment( |
126 views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); | 130 views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); |
127 view->SetLayoutManager(layout); | 131 view->SetLayoutManager(layout); |
128 | 132 |
129 // "Cards accepted" label is "disabled" grey. | 133 // "Cards accepted" label is "disabled" grey. |
130 std::unique_ptr<views::Label> label = base::MakeUnique<views::Label>( | 134 std::unique_ptr<views::Label> label = base::MakeUnique<views::Label>( |
131 l10n_util::GetStringUTF16(IDS_PAYMENTS_ACCEPTED_CARDS_LABEL)); | 135 l10n_util::GetStringUTF16(IDS_PAYMENTS_ACCEPTED_CARDS_LABEL)); |
132 label->SetDisabledColor(label->GetNativeTheme()->GetSystemColor( | 136 label->SetDisabledColor(label->GetNativeTheme()->GetSystemColor( |
133 ui::NativeTheme::kColorId_LabelDisabledColor)); | 137 ui::NativeTheme::kColorId_LabelDisabledColor)); |
(...skipping 19 matching lines...) Expand all Loading... |
153 base::UTF8ToUTF16(supported_network)); | 157 base::UTF8ToUTF16(supported_network)); |
154 card_icon_view->SetImageSize(kCardIconSize); | 158 card_icon_view->SetImageSize(kCardIconSize); |
155 | 159 |
156 icons_row->AddChildView(card_icon_view.release()); | 160 icons_row->AddChildView(card_icon_view.release()); |
157 } | 161 } |
158 view->AddChildView(icons_row.release()); | 162 view->AddChildView(icons_row.release()); |
159 | 163 |
160 return view; | 164 return view; |
161 } | 165 } |
162 | 166 |
163 // Creates the "Billing Address" custom field view. | |
164 // +------------------------------------+ | |
165 // Label* | | Combobox | | Add button | | | |
166 // +------------------------------------+ | |
167 std::unique_ptr<views::View> | 167 std::unique_ptr<views::View> |
168 CreditCardEditorViewController::CreateCustomFieldView( | 168 CreditCardEditorViewController::CreateExtraViewForField( |
169 autofill::ServerFieldType type) { | 169 autofill::ServerFieldType type) { |
170 if (type != kBillingAddressType) | 170 if (type != kBillingAddressType) |
171 return std::unique_ptr<views::View>(); | 171 return nullptr; |
172 std::unique_ptr<views::View> view = base::MakeUnique<views::View>(); | |
173 | 172 |
174 std::unique_ptr<views::GridLayout> layout = | 173 std::unique_ptr<views::View> button_view = base::MakeUnique<views::View>(); |
175 base::MakeUnique<views::GridLayout>(view.get()); | 174 button_view->SetLayoutManager(new views::FillLayout); |
176 | |
177 // Combobox column. | |
178 views::ColumnSet* columns = layout->AddColumnSet(0); | |
179 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 0, | |
180 views::GridLayout::FIXED, kMaximumLabelWidth, 0); | |
181 | |
182 // This is the horizontal padding between the combobox and the add button. | |
183 constexpr int kComboboxAddButtonHorizontalPadding = 8; | |
184 columns->AddPaddingColumn(0, kComboboxAddButtonHorizontalPadding); | |
185 | |
186 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0, | |
187 views::GridLayout::USE_PREF, 0, 0); | |
188 | |
189 layout->StartRow(0, 0); | |
190 | |
191 EditorField billing_address_field( | |
192 kBillingAddressType, | |
193 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_BILLING_ADDRESS), | |
194 EditorField::LengthHint::HINT_SHORT, /*required=*/true, | |
195 EditorField::ControlType::COMBOBOX); | |
196 | |
197 // The combobox filled with potential billing addresses. | |
198 std::unique_ptr<autofill::AddressComboboxModel> address_combobox_model = | |
199 base::MakeUnique<autofill::AddressComboboxModel>( | |
200 *state()->GetPersonalDataManager(), state()->GetApplicationLocale()); | |
201 int selected_index = -1; | |
202 if (credit_card_to_edit_ && | |
203 !credit_card_to_edit_->billing_address_id().empty()) { | |
204 selected_index = address_combobox_model->GetIndexOfIdentifier( | |
205 credit_card_to_edit_->billing_address_id()); | |
206 } | |
207 // This takes care of rare cases where the the billing address set on the | |
208 // current card isn't valid anymore. | |
209 if (selected_index == -1) | |
210 selected_index = address_combobox_model->GetDefaultIndex(); | |
211 | |
212 ValidatingCombobox* combobox = | |
213 new ValidatingCombobox(std::move(address_combobox_model), | |
214 CreateValidationDelegate(billing_address_field)); | |
215 combobox->SetSelectedIndex(selected_index); | |
216 | |
217 // Using autofill field type as a view ID (for testing). | |
218 combobox->set_id(static_cast<int>(billing_address_field.type)); | |
219 combobox->set_listener(this); | |
220 | |
221 // |combobox| will now be owned by |row|. | |
222 layout->AddView(combobox); | |
223 | 175 |
224 // The button to add new billing addresses. | 176 // The button to add new billing addresses. |
225 std::unique_ptr<views::Button> add_button( | 177 std::unique_ptr<views::Button> add_button( |
226 views::MdTextButton::Create(this, l10n_util::GetStringUTF16(IDS_ADD))); | 178 views::MdTextButton::Create(this, l10n_util::GetStringUTF16(IDS_ADD))); |
227 add_button->set_id( | 179 add_button->set_id( |
228 static_cast<int>(DialogViewID::ADD_BILLING_ADDRESS_BUTTON)); | 180 static_cast<int>(DialogViewID::ADD_BILLING_ADDRESS_BUTTON)); |
229 add_button->set_tag(add_billing_address_button_tag_); | 181 add_button->set_tag(add_billing_address_button_tag_); |
230 | 182 button_view->AddChildView(add_button.release()); |
231 // |add_button| will now be owned by |row|. | 183 return button_view; |
232 layout->AddView(add_button.release()); | |
233 view->SetLayoutManager(layout.release()); | |
234 return view; | |
235 } | 184 } |
236 | 185 |
237 std::vector<EditorField> CreditCardEditorViewController::GetFieldDefinitions() { | 186 std::vector<EditorField> CreditCardEditorViewController::GetFieldDefinitions() { |
238 return std::vector<EditorField>{ | 187 return std::vector<EditorField>{ |
239 {autofill::CREDIT_CARD_NUMBER, | 188 {autofill::CREDIT_CARD_NUMBER, |
240 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER), | 189 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER), |
241 EditorField::LengthHint::HINT_LONG, /* required= */ true}, | 190 EditorField::LengthHint::HINT_SHORT, /* required= */ true}, |
242 {autofill::CREDIT_CARD_NAME_FULL, | 191 {autofill::CREDIT_CARD_NAME_FULL, |
243 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_NAME_ON_CARD), | 192 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_NAME_ON_CARD), |
244 EditorField::LengthHint::HINT_LONG, /* required= */ true}, | 193 EditorField::LengthHint::HINT_SHORT, /* required= */ true}, |
245 {autofill::CREDIT_CARD_EXP_MONTH, | 194 {autofill::CREDIT_CARD_EXP_MONTH, |
246 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_MONTH), | 195 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_MONTH), |
247 EditorField::LengthHint::HINT_SHORT, /* required= */ true, | 196 EditorField::LengthHint::HINT_SHORT, /* required= */ true, |
248 EditorField::ControlType::COMBOBOX}, | 197 EditorField::ControlType::COMBOBOX}, |
249 {autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, | 198 {autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, |
250 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_YEAR), | 199 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_YEAR), |
251 EditorField::LengthHint::HINT_SHORT, /* required= */ true, | 200 EditorField::LengthHint::HINT_SHORT, /* required= */ true, |
252 EditorField::ControlType::COMBOBOX}, | 201 EditorField::ControlType::COMBOBOX}, |
253 {kBillingAddressType, | 202 {kBillingAddressType, |
254 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_BILLING_ADDRESS), | 203 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_BILLING_ADDRESS), |
255 EditorField::LengthHint::HINT_LONG, /* required= */ true, | 204 EditorField::LengthHint::HINT_SHORT, /* required= */ true, |
256 EditorField::ControlType::CUSTOMFIELD}}; | 205 EditorField::ControlType::COMBOBOX}}; |
257 } | 206 } |
258 | 207 |
259 base::string16 CreditCardEditorViewController::GetInitialValueForType( | 208 base::string16 CreditCardEditorViewController::GetInitialValueForType( |
260 autofill::ServerFieldType type) { | 209 autofill::ServerFieldType type) { |
261 if (!credit_card_to_edit_) | 210 if (!credit_card_to_edit_ || type == kBillingAddressType) |
262 return base::string16(); | 211 return base::string16(); |
263 | 212 |
264 return credit_card_to_edit_->GetInfo(autofill::AutofillType(type), | 213 return credit_card_to_edit_->GetInfo(autofill::AutofillType(type), |
265 state()->GetApplicationLocale()); | 214 state()->GetApplicationLocale()); |
266 } | 215 } |
267 | 216 |
268 bool CreditCardEditorViewController::ValidateModelAndSave() { | 217 bool CreditCardEditorViewController::ValidateModelAndSave() { |
269 const std::string& locale = state()->GetApplicationLocale(); | 218 const std::string& locale = state()->GetApplicationLocale(); |
270 // Use a temporary object for validation. | 219 // Use a temporary object for validation. |
271 autofill::CreditCard credit_card; | 220 autofill::CreditCard credit_card; |
272 credit_card.set_origin(autofill::kSettingsOrigin); | 221 credit_card.set_origin(autofill::kSettingsOrigin); |
273 | 222 |
274 for (const auto& field : text_fields()) { | 223 for (const auto& field : text_fields()) { |
275 // ValidatingTextfield* is the key, EditorField is the value. | 224 // ValidatingTextfield* is the key, EditorField is the value. |
276 DCHECK_EQ(autofill::CREDIT_CARD, | 225 DCHECK_EQ(autofill::CREDIT_CARD, |
277 autofill::AutofillType(field.second.type).group()); | 226 autofill::AutofillType(field.second.type).group()); |
278 if (field.first->invalid()) | 227 if (field.first->invalid()) |
279 return false; | 228 return false; |
280 | 229 |
281 credit_card.SetInfo(autofill::AutofillType(field.second.type), | 230 credit_card.SetInfo(autofill::AutofillType(field.second.type), |
282 field.first->text(), locale); | 231 field.first->text(), locale); |
283 } | 232 } |
284 for (const auto& field : comboboxes()) { | 233 for (const auto& field : comboboxes()) { |
285 // ValidatingCombobox* is the key, EditorField is the value. | 234 // ValidatingCombobox* is the key, EditorField is the value. |
286 DCHECK_EQ(autofill::CREDIT_CARD, | |
287 autofill::AutofillType(field.second.type).group()); | |
288 ValidatingCombobox* combobox = field.first; | 235 ValidatingCombobox* combobox = field.first; |
289 if (combobox->invalid()) | 236 if (combobox->invalid()) |
290 return false; | 237 return false; |
291 | 238 |
292 credit_card.SetInfo(autofill::AutofillType(field.second.type), | 239 if (field.second.type == kBillingAddressType) { |
293 combobox->GetTextForRow(combobox->selected_index()), | 240 views::Combobox* address_combobox = static_cast<views::Combobox*>( |
294 locale); | 241 dialog()->GetViewByID(kBillingAddressType)); |
| 242 autofill::AddressComboboxModel* model = |
| 243 static_cast<autofill::AddressComboboxModel*>( |
| 244 address_combobox->model()); |
| 245 |
| 246 credit_card.set_billing_address_id( |
| 247 model->GetItemIdentifierAt(address_combobox->selected_index())); |
| 248 } else { |
| 249 credit_card.SetInfo(autofill::AutofillType(field.second.type), |
| 250 combobox->GetTextForRow(combobox->selected_index()), |
| 251 locale); |
| 252 } |
295 } | 253 } |
296 | 254 |
297 views::Combobox* address_combobox = | |
298 static_cast<views::Combobox*>(dialog()->GetViewByID(kBillingAddressType)); | |
299 autofill::AddressComboboxModel* model = | |
300 static_cast<autofill::AddressComboboxModel*>(address_combobox->model()); | |
301 | |
302 credit_card.set_billing_address_id( | |
303 model->GetItemIdentifierAt(address_combobox->selected_index())); | |
304 | |
305 // TODO(crbug.com/711365): Display global error message. | 255 // TODO(crbug.com/711365): Display global error message. |
306 if (autofill::GetCompletionStatusForCard( | 256 if (autofill::GetCompletionStatusForCard( |
307 credit_card, locale, | 257 credit_card, locale, |
308 state()->GetPersonalDataManager()->GetProfiles()) != | 258 state()->GetPersonalDataManager()->GetProfiles()) != |
309 autofill::CREDIT_CARD_COMPLETE) { | 259 autofill::CREDIT_CARD_COMPLETE) { |
310 return false; | 260 return false; |
311 } | 261 } |
312 | 262 |
313 if (!credit_card_to_edit_) { | 263 if (!credit_card_to_edit_) { |
314 // Add the card (will not add a duplicate). | 264 // Add the card (will not add a duplicate). |
315 state()->GetPersonalDataManager()->AddCreditCard(credit_card); | 265 state()->GetPersonalDataManager()->AddCreditCard(credit_card); |
316 std::move(on_added_).Run(credit_card); | 266 std::move(on_added_).Run(credit_card); |
317 } else { | 267 } else { |
318 credit_card_to_edit_->set_billing_address_id( | 268 credit_card_to_edit_->set_billing_address_id( |
319 credit_card.billing_address_id()); | 269 credit_card.billing_address_id()); |
320 // We were in edit mode. Copy the data from the temporary object to retain | 270 // We were in edit mode. Copy the data from the temporary object to retain |
321 // the edited object's other properties (use count, use date, guid, etc.). | 271 // the edited object's other properties (use count, use date, guid, etc.). |
322 for (const auto& field : text_fields()) { | 272 for (const auto& field : text_fields()) { |
323 credit_card_to_edit_->SetInfo( | 273 credit_card_to_edit_->SetInfo( |
324 autofill::AutofillType(field.second.type), | 274 autofill::AutofillType(field.second.type), |
325 credit_card.GetInfo(autofill::AutofillType(field.second.type), | 275 credit_card.GetInfo(autofill::AutofillType(field.second.type), |
326 locale), | 276 locale), |
327 locale); | 277 locale); |
328 } | 278 } |
329 for (const auto& field : comboboxes()) { | 279 for (const auto& field : comboboxes()) { |
| 280 // The billing address is transfered above. |
| 281 if (field.second.type == kBillingAddressType) |
| 282 continue; |
| 283 |
330 credit_card_to_edit_->SetInfo( | 284 credit_card_to_edit_->SetInfo( |
331 autofill::AutofillType(field.second.type), | 285 autofill::AutofillType(field.second.type), |
332 credit_card.GetInfo(autofill::AutofillType(field.second.type), | 286 credit_card.GetInfo(autofill::AutofillType(field.second.type), |
333 locale), | 287 locale), |
334 locale); | 288 locale); |
335 } | 289 } |
336 state()->GetPersonalDataManager()->UpdateCreditCard(*credit_card_to_edit_); | 290 state()->GetPersonalDataManager()->UpdateCreditCard(*credit_card_to_edit_); |
337 std::move(on_edited_).Run(); | 291 std::move(on_edited_).Run(); |
338 } | 292 } |
339 | 293 |
(...skipping 19 matching lines...) Expand all Loading... |
359 switch (type) { | 313 switch (type) { |
360 case autofill::CREDIT_CARD_EXP_MONTH: { | 314 case autofill::CREDIT_CARD_EXP_MONTH: { |
361 int default_index = 0; | 315 int default_index = 0; |
362 std::vector<base::string16> months = | 316 std::vector<base::string16> months = |
363 GetExpirationMonthItems(&default_index); | 317 GetExpirationMonthItems(&default_index); |
364 return base::MakeUnique<PreselectedComboboxModel>(months, default_index); | 318 return base::MakeUnique<PreselectedComboboxModel>(months, default_index); |
365 } | 319 } |
366 case autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR: | 320 case autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR: |
367 return base::MakeUnique<ui::SimpleComboboxModel>( | 321 return base::MakeUnique<ui::SimpleComboboxModel>( |
368 GetExpirationYearItems()); | 322 GetExpirationYearItems()); |
| 323 case kBillingAddressType: |
| 324 // The combobox filled with potential billing addresses. It's fine to pass |
| 325 // empty string as the default selected guid if there are no cards being |
| 326 // edited. |
| 327 return base::MakeUnique<autofill::AddressComboboxModel>( |
| 328 *state()->GetPersonalDataManager(), state()->GetApplicationLocale(), |
| 329 credit_card_to_edit_ ? credit_card_to_edit_->billing_address_id() |
| 330 : ""); |
369 default: | 331 default: |
370 NOTREACHED(); | 332 NOTREACHED(); |
371 break; | 333 break; |
372 } | 334 } |
373 return std::unique_ptr<ui::ComboboxModel>(); | 335 return std::unique_ptr<ui::ComboboxModel>(); |
374 } | 336 } |
375 | 337 |
376 base::string16 CreditCardEditorViewController::GetSheetTitle() { | 338 base::string16 CreditCardEditorViewController::GetSheetTitle() { |
377 if (!credit_card_to_edit_) | 339 if (!credit_card_to_edit_) |
378 return l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_CARD); | 340 return l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_CARD); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 controller_->DisplayErrorMessageForField(field_, displayed_message); | 429 controller_->DisplayErrorMessageForField(field_, displayed_message); |
468 return is_required_valid; | 430 return is_required_valid; |
469 } | 431 } |
470 | 432 |
471 bool CreditCardEditorViewController::GetSheetId(DialogViewID* sheet_id) { | 433 bool CreditCardEditorViewController::GetSheetId(DialogViewID* sheet_id) { |
472 *sheet_id = DialogViewID::CREDIT_CARD_EDITOR_SHEET; | 434 *sheet_id = DialogViewID::CREDIT_CARD_EDITOR_SHEET; |
473 return true; | 435 return true; |
474 } | 436 } |
475 | 437 |
476 } // namespace payments | 438 } // namespace payments |
OLD | NEW |