Chromium Code Reviews| 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/shipping_address_editor_view_controll er.h" | 5 #include "chrome/browser/ui/views/payments/shipping_address_editor_view_controll er.h" |
| 6 | 6 |
| 7 #include <utility> | |
| 8 | |
| 9 #include "base/bind.h" | 7 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 11 #include "base/callback.h" | 9 #include "base/callback.h" |
| 12 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h" | 13 #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h" |
| 16 #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h" | 14 #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h" |
| 17 #include "chrome/browser/ui/views/payments/validating_combobox.h" | 15 #include "chrome/browser/ui/views/payments/validating_combobox.h" |
| 18 #include "chrome/browser/ui/views/payments/validating_textfield.h" | 16 #include "chrome/browser/ui/views/payments/validating_textfield.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 BackNavigationType back_navigation_type, | 70 BackNavigationType back_navigation_type, |
| 73 base::OnceClosure on_edited, | 71 base::OnceClosure on_edited, |
| 74 base::OnceCallback<void(const autofill::AutofillProfile&)> on_added, | 72 base::OnceCallback<void(const autofill::AutofillProfile&)> on_added, |
| 75 autofill::AutofillProfile* profile) | 73 autofill::AutofillProfile* profile) |
| 76 : EditorViewController(spec, state, dialog, back_navigation_type), | 74 : EditorViewController(spec, state, dialog, back_navigation_type), |
| 77 on_edited_(std::move(on_edited)), | 75 on_edited_(std::move(on_edited)), |
| 78 on_added_(std::move(on_added)), | 76 on_added_(std::move(on_added)), |
| 79 profile_to_edit_(profile), | 77 profile_to_edit_(profile), |
| 80 chosen_country_index_(0), | 78 chosen_country_index_(0), |
| 81 failed_to_load_region_data_(false) { | 79 failed_to_load_region_data_(false) { |
| 80 autofill::CountryComboboxModel model; | |
|
Mathieu
2017/05/16 20:10:06
I would put lines 80-112 inside a private function
MAD
2017/05/17 12:38:11
Done.
| |
| 81 model.SetCountries(*state->GetPersonalDataManager(), | |
| 82 base::Callback<bool(const std::string&)>(), | |
| 83 state->GetApplicationLocale()); | |
| 84 for (size_t i = 0; i < model.countries().size(); ++i) { | |
| 85 autofill::AutofillCountry* country(model.countries()[i].get()); | |
| 86 if (country) { | |
| 87 countries_.push_back( | |
| 88 std::make_pair(country->country_code(), country->name())); | |
| 89 } else { | |
| 90 // Separator. | |
| 91 countries_.push_back(std::make_pair("", base::UTF8ToUTF16(""))); | |
| 92 } | |
| 93 } | |
| 94 // If there is a profile to edit, make sure to use its country for the initial | |
| 95 // |chosen_country_index_|. | |
| 96 if (profile_to_edit_) { | |
| 97 autofill::AutofillType country_type(autofill::ADDRESS_HOME_COUNTRY); | |
| 98 base::string16 chosen_country( | |
| 99 profile_to_edit_->GetInfo(country_type, state->GetApplicationLocale())); | |
| 100 for (chosen_country_index_ = 0; chosen_country_index_ < countries_.size(); | |
| 101 ++chosen_country_index_) { | |
| 102 if (chosen_country == countries_[chosen_country_index_].second) | |
| 103 break; | |
| 104 } | |
| 105 if (chosen_country_index_ >= countries_.size()) { | |
| 106 LOG(ERROR) << "Unexpected country: " << chosen_country; | |
| 107 CHECK_GT(countries_.size(), 0); | |
|
Mathieu
2017/05/16 20:10:06
could this ever happen in the wild? Crashing is pr
MAD
2017/05/17 12:38:10
It would crash below otherwise...
But now that y
| |
| 108 chosen_country_index_ = 0; | |
| 109 profile_to_edit_->SetInfo(country_type, | |
| 110 countries_[chosen_country_index_].second, | |
| 111 state->GetApplicationLocale()); | |
| 112 } | |
| 113 } | |
| 82 UpdateEditorFields(); | 114 UpdateEditorFields(); |
| 83 } | 115 } |
| 84 | 116 |
| 85 ShippingAddressEditorViewController::~ShippingAddressEditorViewController() {} | 117 ShippingAddressEditorViewController::~ShippingAddressEditorViewController() {} |
| 86 | 118 |
| 87 std::vector<EditorField> | 119 std::vector<EditorField> |
| 88 ShippingAddressEditorViewController::GetFieldDefinitions() { | 120 ShippingAddressEditorViewController::GetFieldDefinitions() { |
| 89 return editor_fields_; | 121 return editor_fields_; |
| 90 } | 122 } |
| 91 | 123 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 std::unique_ptr<ui::ComboboxModel> | 176 std::unique_ptr<ui::ComboboxModel> |
| 145 ShippingAddressEditorViewController::GetComboboxModelForType( | 177 ShippingAddressEditorViewController::GetComboboxModelForType( |
| 146 const autofill::ServerFieldType& type) { | 178 const autofill::ServerFieldType& type) { |
| 147 switch (type) { | 179 switch (type) { |
| 148 case autofill::ADDRESS_HOME_COUNTRY: { | 180 case autofill::ADDRESS_HOME_COUNTRY: { |
| 149 std::unique_ptr<autofill::CountryComboboxModel> model = | 181 std::unique_ptr<autofill::CountryComboboxModel> model = |
| 150 base::MakeUnique<autofill::CountryComboboxModel>(); | 182 base::MakeUnique<autofill::CountryComboboxModel>(); |
| 151 model->SetCountries(*state()->GetPersonalDataManager(), | 183 model->SetCountries(*state()->GetPersonalDataManager(), |
| 152 base::Callback<bool(const std::string&)>(), | 184 base::Callback<bool(const std::string&)>(), |
| 153 state()->GetApplicationLocale()); | 185 state()->GetApplicationLocale()); |
| 154 country_codes_.clear(); | |
| 155 for (size_t i = 0; i < model->countries().size(); ++i) { | |
| 156 if (model->countries()[i].get()) | |
| 157 country_codes_.push_back(model->countries()[i]->country_code()); | |
| 158 else | |
| 159 country_codes_.push_back(""); // Separator. | |
| 160 } | |
| 161 return std::move(model); | 186 return std::move(model); |
| 162 } | 187 } |
| 163 case autofill::ADDRESS_HOME_STATE: { | 188 case autofill::ADDRESS_HOME_STATE: { |
| 164 std::unique_ptr<autofill::RegionComboboxModel> model = | 189 std::unique_ptr<autofill::RegionComboboxModel> model = |
| 165 base::MakeUnique<autofill::RegionComboboxModel>(); | 190 base::MakeUnique<autofill::RegionComboboxModel>(); |
| 166 model->LoadRegionData(country_codes_[chosen_country_index_], | 191 model->LoadRegionData(countries_[chosen_country_index_].first, |
| 167 state()->GetRegionDataLoader(), | 192 state()->GetRegionDataLoader(), |
| 168 /*timeout_ms=*/5000); | 193 /*timeout_ms=*/5000); |
| 169 if (!model->IsPendingRegionDataLoad()) { | 194 if (!model->IsPendingRegionDataLoad()) { |
| 170 // If the data was already pre-loaded, the observer won't get notified | 195 // If the data was already pre-loaded, the observer won't get notified |
| 171 // so we have to check for failure here. | 196 // so we have to check for failure here. |
| 172 failed_to_load_region_data_ = model->failed_to_load_data(); | 197 failed_to_load_region_data_ = model->failed_to_load_data(); |
| 173 if (failed_to_load_region_data_) { | 198 if (failed_to_load_region_data_) { |
| 174 // We can update the view synchronously while building the view. | 199 // We can't update the view synchronously while building the view. |
| 175 OnDataChanged(/*synchronous=*/false); | 200 OnDataChanged(/*synchronous=*/false); |
| 176 } | 201 } |
| 177 } | 202 } |
| 178 return std::move(model); | 203 return std::move(model); |
| 179 } | 204 } |
| 180 default: | 205 default: |
| 181 NOTREACHED(); | 206 NOTREACHED(); |
| 182 break; | 207 break; |
| 183 } | 208 } |
| 184 return std::unique_ptr<ui::ComboboxModel>(); | 209 return std::unique_ptr<ui::ComboboxModel>(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 ShippingAddressEditorViewController::CreatePrimaryButton() { | 247 ShippingAddressEditorViewController::CreatePrimaryButton() { |
| 223 std::unique_ptr<views::Button> button( | 248 std::unique_ptr<views::Button> button( |
| 224 EditorViewController::CreatePrimaryButton()); | 249 EditorViewController::CreatePrimaryButton()); |
| 225 button->set_id(static_cast<int>(DialogViewID::SAVE_ADDRESS_BUTTON)); | 250 button->set_id(static_cast<int>(DialogViewID::SAVE_ADDRESS_BUTTON)); |
| 226 return button; | 251 return button; |
| 227 } | 252 } |
| 228 | 253 |
| 229 void ShippingAddressEditorViewController::UpdateEditorFields() { | 254 void ShippingAddressEditorViewController::UpdateEditorFields() { |
| 230 editor_fields_.clear(); | 255 editor_fields_.clear(); |
| 231 std::string chosen_country_code; | 256 std::string chosen_country_code; |
| 232 if (chosen_country_index_ < country_codes_.size()) | 257 if (chosen_country_index_ < countries_.size()) |
| 233 chosen_country_code = country_codes_[chosen_country_index_]; | 258 chosen_country_code = countries_[chosen_country_index_].first; |
| 234 | 259 |
| 235 std::unique_ptr<base::ListValue> components(new base::ListValue); | 260 std::unique_ptr<base::ListValue> components(new base::ListValue); |
| 236 std::string unused; | 261 std::string unused; |
| 237 autofill::GetAddressComponents(chosen_country_code, | 262 autofill::GetAddressComponents(chosen_country_code, |
| 238 state()->GetApplicationLocale(), | 263 state()->GetApplicationLocale(), |
| 239 components.get(), &unused); | 264 components.get(), &unused); |
| 240 for (size_t line_index = 0; line_index < components->GetSize(); | 265 for (size_t line_index = 0; line_index < components->GetSize(); |
| 241 ++line_index) { | 266 ++line_index) { |
| 242 const base::ListValue* line = nullptr; | 267 const base::ListValue* line = nullptr; |
| 243 if (!components->GetList(line_index, &line)) { | 268 if (!components->GetList(line_index, &line)) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 FROM_HERE, | 341 FROM_HERE, |
| 317 base::BindOnce(&ShippingAddressEditorViewController::UpdateEditorView, | 342 base::BindOnce(&ShippingAddressEditorViewController::UpdateEditorView, |
| 318 base::Unretained(this))); | 343 base::Unretained(this))); |
| 319 } | 344 } |
| 320 } | 345 } |
| 321 | 346 |
| 322 bool ShippingAddressEditorViewController::SaveFieldsToProfile( | 347 bool ShippingAddressEditorViewController::SaveFieldsToProfile( |
| 323 autofill::AutofillProfile* profile, | 348 autofill::AutofillProfile* profile, |
| 324 bool ignore_errors) { | 349 bool ignore_errors) { |
| 325 const std::string& locale = state()->GetApplicationLocale(); | 350 const std::string& locale = state()->GetApplicationLocale(); |
| 351 // The country must be set first, because the profile uses the country to | |
| 352 // interpret some of the data (e.g., phone numbers) passed to SetInfo. | |
| 353 views::Combobox* combobox = static_cast<views::Combobox*>( | |
| 354 dialog()->GetViewByID(autofill::ADDRESS_HOME_COUNTRY)); | |
| 355 // The combobox can be null when saving to temporary profile while updating | |
| 356 // the view. | |
| 357 if (combobox) { | |
| 358 base::string16 country(combobox->GetTextForRow(combobox->selected_index())); | |
| 359 bool success = | |
| 360 profile->SetInfo(autofill::AutofillType(autofill::ADDRESS_HOME_COUNTRY), | |
| 361 country, locale); | |
| 362 LOG_IF(ERROR, !success && !ignore_errors) | |
| 363 << "Can't set profile country to: " << country; | |
| 364 if (!success && !ignore_errors) | |
| 365 return false; | |
| 366 } else { | |
| 367 DCHECK_EQ(temporary_profile_.get(), profile); | |
| 368 } | |
| 369 | |
| 326 bool success = true; | 370 bool success = true; |
| 327 for (const auto& field : text_fields()) { | 371 for (const auto& field : text_fields()) { |
| 328 // Force a blur in case the value was left untouched. | 372 // Force a blur in case the value was left untouched. |
| 329 field.first->OnBlur(); | 373 field.first->OnBlur(); |
| 330 // ValidatingTextfield* is the key, EditorField is the value. | 374 // ValidatingTextfield* is the key, EditorField is the value. |
| 331 if (field.first->invalid()) { | 375 if (field.first->invalid()) { |
| 332 success = false; | 376 success = false; |
| 333 } else { | 377 } else { |
| 334 success = profile->SetInfo(autofill::AutofillType(field.second.type), | 378 success = profile->SetInfo(autofill::AutofillType(field.second.type), |
| 335 field.first->text(), locale); | 379 field.first->text(), locale); |
| 336 } | 380 } |
| 337 LOG_IF(ERROR, !success && !ignore_errors) | 381 LOG_IF(ERROR, !success && !ignore_errors) |
| 338 << "Can't setinfo(" << field.second.type << ", " << field.first->text(); | 382 << "Can't setinfo(" << field.second.type << ", " << field.first->text(); |
| 339 if (!success && !ignore_errors) | 383 if (!success && !ignore_errors) |
| 340 return false; | 384 return false; |
| 341 } | 385 } |
| 342 for (const auto& field : comboboxes()) { | 386 for (const auto& field : comboboxes()) { |
| 343 // ValidatingCombobox* is the key, EditorField is the value. | 387 // ValidatingCombobox* is the key, EditorField is the value. |
| 344 ValidatingCombobox* combobox = field.first; | 388 ValidatingCombobox* combobox = field.first; |
| 389 // The country has already been dealt with. | |
| 390 if (combobox->id() == autofill::ADDRESS_HOME_COUNTRY) | |
| 391 continue; | |
| 345 if (combobox->invalid()) { | 392 if (combobox->invalid()) { |
| 346 success = false; | 393 success = false; |
| 347 } else { | 394 } else { |
| 348 if (combobox->id() == autofill::ADDRESS_HOME_COUNTRY) { | 395 success = profile->SetInfo( |
| 349 success = profile->SetInfo( | 396 autofill::AutofillType(field.second.type), |
| 350 autofill::AutofillType(field.second.type), | 397 combobox->GetTextForRow(combobox->selected_index()), locale); |
| 351 base::UTF8ToUTF16(country_codes_[combobox->selected_index()]), | |
| 352 locale); | |
| 353 } else { | |
| 354 success = profile->SetInfo( | |
| 355 autofill::AutofillType(field.second.type), | |
| 356 combobox->GetTextForRow(combobox->selected_index()), locale); | |
| 357 } | |
| 358 } | 398 } |
| 359 LOG_IF(ERROR, !success && !ignore_errors) | 399 LOG_IF(ERROR, !success && !ignore_errors) |
| 360 << "Can't setinfo(" << field.second.type << ", " | 400 << "Can't setinfo(" << field.second.type << ", " |
| 361 << combobox->GetTextForRow(combobox->selected_index()); | 401 << combobox->GetTextForRow(combobox->selected_index()); |
| 362 if (!success && !ignore_errors) | 402 if (!success && !ignore_errors) |
| 363 return false; | 403 return false; |
| 364 } | 404 } |
| 365 return success; | 405 return success; |
| 366 } | 406 } |
| 367 | 407 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 void ShippingAddressEditorViewController::ShippingAddressValidationDelegate:: | 448 void ShippingAddressEditorViewController::ShippingAddressValidationDelegate:: |
| 409 ComboboxModelChanged(views::Combobox* combobox) { | 449 ComboboxModelChanged(views::Combobox* combobox) { |
| 410 controller_->OnComboboxModelChanged(combobox); | 450 controller_->OnComboboxModelChanged(combobox); |
| 411 } | 451 } |
| 412 | 452 |
| 413 bool ShippingAddressEditorViewController::ShippingAddressValidationDelegate:: | 453 bool ShippingAddressEditorViewController::ShippingAddressValidationDelegate:: |
| 414 ValidateValue(const base::string16& value) { | 454 ValidateValue(const base::string16& value) { |
| 415 if (!value.empty()) { | 455 if (!value.empty()) { |
| 416 if (field_.type == autofill::PHONE_HOME_WHOLE_NUMBER && | 456 if (field_.type == autofill::PHONE_HOME_WHOLE_NUMBER && |
| 417 !autofill::IsValidPhoneNumber( | 457 !autofill::IsValidPhoneNumber( |
| 418 value, | 458 value, controller_->countries_[controller_->chosen_country_index_] |
| 419 controller_->country_codes_[controller_->chosen_country_index_])) { | 459 .first)) { |
| 420 controller_->DisplayErrorMessageForField( | 460 controller_->DisplayErrorMessageForField( |
| 421 field_, l10n_util::GetStringUTF16( | 461 field_, l10n_util::GetStringUTF16( |
| 422 IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE)); | 462 IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE)); |
| 423 return false; | 463 return false; |
| 424 } | 464 } |
| 425 // As long as other field types are non-empty, they are valid. | 465 // As long as other field types are non-empty, they are valid. |
| 426 controller_->DisplayErrorMessageForField(field_, base::ASCIIToUTF16("")); | 466 controller_->DisplayErrorMessageForField(field_, base::ASCIIToUTF16("")); |
| 427 return true; | 467 return true; |
| 428 } | 468 } |
| 429 bool is_required_valid = !field_.required; | 469 bool is_required_valid = !field_.required; |
| 430 const base::string16 displayed_message = | 470 const base::string16 displayed_message = |
| 431 is_required_valid ? base::ASCIIToUTF16("") | 471 is_required_valid ? base::ASCIIToUTF16("") |
| 432 : l10n_util::GetStringUTF16( | 472 : l10n_util::GetStringUTF16( |
| 433 IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE); | 473 IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE); |
| 434 controller_->DisplayErrorMessageForField(field_, displayed_message); | 474 controller_->DisplayErrorMessageForField(field_, displayed_message); |
| 435 return is_required_valid; | 475 return is_required_valid; |
| 436 } | 476 } |
| 437 | 477 |
| 438 } // namespace payments | 478 } // namespace payments |
| OLD | NEW |