OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/autofill/autofill_dialog_controller_impl.h" | 5 #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_number_conversions.h" | |
10 #include "base/string_split.h" | 11 #include "base/string_split.h" |
11 #include "base/string_util.h" | 12 #include "base/string_util.h" |
12 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
13 #include "chrome/browser/autofill/autofill_country.h" | 14 #include "chrome/browser/autofill/autofill_country.h" |
14 #include "chrome/browser/autofill/autofill_manager.h" | 15 #include "chrome/browser/autofill/autofill_manager.h" |
15 #include "chrome/browser/autofill/autofill_type.h" | 16 #include "chrome/browser/autofill/autofill_type.h" |
16 #include "chrome/browser/autofill/personal_data_manager.h" | 17 #include "chrome/browser/autofill/personal_data_manager.h" |
17 #include "chrome/browser/autofill/personal_data_manager_factory.h" | 18 #include "chrome/browser/autofill/personal_data_manager_factory.h" |
18 #include "chrome/browser/autofill/validation.h" | 19 #include "chrome/browser/autofill/validation.h" |
19 #include "chrome/browser/autofill/wallet/full_wallet.h" | 20 #include "chrome/browser/autofill/wallet/full_wallet.h" |
20 #include "chrome/browser/autofill/wallet/wallet_items.h" | 21 #include "chrome/browser/autofill/wallet/wallet_items.h" |
21 #include "chrome/browser/autofill/wallet/wallet_service_url.h" | 22 #include "chrome/browser/autofill/wallet/wallet_service_url.h" |
22 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
23 #include "chrome/browser/ui/autofill/autofill_dialog_view.h" | 24 #include "chrome/browser/ui/autofill/autofill_dialog_view.h" |
25 #include "chrome/browser/ui/autofill/data_model_wrapper.h" | |
24 #include "chrome/common/form_data.h" | 26 #include "chrome/common/form_data.h" |
25 #include "content/public/browser/navigation_controller.h" | 27 #include "content/public/browser/navigation_controller.h" |
26 #include "content/public/browser/navigation_details.h" | 28 #include "content/public/browser/navigation_details.h" |
27 #include "content/public/browser/navigation_entry.h" | 29 #include "content/public/browser/navigation_entry.h" |
28 #include "content/public/browser/notification_service.h" | 30 #include "content/public/browser/notification_service.h" |
29 #include "content/public/browser/notification_types.h" | 31 #include "content/public/browser/notification_types.h" |
30 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
31 #include "content/public/common/url_constants.h" | 33 #include "content/public/common/url_constants.h" |
32 #include "grit/chromium_strings.h" | 34 #include "grit/chromium_strings.h" |
33 #include "grit/generated_resources.h" | 35 #include "grit/generated_resources.h" |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 return string16(); | 373 return string16(); |
372 | 374 |
373 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); | 375 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); |
374 std::string item_key = model->GetItemKeyAt(model->checked_item()); | 376 std::string item_key = model->GetItemKeyAt(model->checked_item()); |
375 if (item_key.empty()) | 377 if (item_key.empty()) |
376 return string16(); | 378 return string16(); |
377 | 379 |
378 if (section == SECTION_EMAIL) | 380 if (section == SECTION_EMAIL) |
379 return model->GetLabelAt(model->checked_item()); | 381 return model->GetLabelAt(model->checked_item()); |
380 | 382 |
381 if (section == SECTION_CC) { | 383 scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section); |
384 return wrapper->GetDisplayText(); | |
385 } | |
386 | |
387 scoped_ptr<DataModelWrapper> AutofillDialogControllerImpl::CreateWrapper( | |
388 DialogSection section) { | |
389 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); | |
390 std::string item_key = model->GetItemKeyAt(model->checked_item()); | |
391 scoped_ptr<DataModelWrapper> wrapper; | |
392 if (item_key.empty()) | |
393 return wrapper.Pass(); | |
394 | |
395 if (CanPayWithWallet()) { | |
396 int index; | |
397 bool success = !base::StringToInt(item_key, &index); | |
Dan Beam
2013/02/15 02:11:45
shouldn't this be without the "!" ?
Evan Stade
2013/02/20 00:03:39
yes
| |
398 DCHECK(success); | |
399 | |
400 if (section == SECTION_CC) { | |
401 wrapper.reset( | |
402 new WalletInstrumentWrapper(wallet_items_->instruments()[index])); | |
403 } else { | |
404 wrapper.reset( | |
405 new WalletAddressWrapper(wallet_items_->addresses()[index])); | |
406 } | |
407 } else if (section == SECTION_CC) { | |
382 CreditCard* card = GetManager()->GetCreditCardByGUID(item_key); | 408 CreditCard* card = GetManager()->GetCreditCardByGUID(item_key); |
383 return card->TypeAndLastFourDigits(); | 409 DCHECK(card); |
410 wrapper.reset(new AutofillCreditCardWrapper(card)); | |
411 } else { | |
412 // Calculate the variant by looking at how many items come from the same | |
413 // FormGroup. TODO(estade): add a test for this. | |
414 size_t variant = 0; | |
415 for (int i = model->checked_item() - 1; i >= 0; --i) { | |
416 if (model->GetItemKeyAt(i) == item_key) | |
417 variant++; | |
418 else | |
419 break; | |
420 } | |
421 | |
422 AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key); | |
423 DCHECK(profile); | |
424 wrapper.reset(new AutofillDataModelWrapper(profile, variant)); | |
384 } | 425 } |
385 | 426 |
386 const std::string app_locale = AutofillCountry::ApplicationLocale(); | 427 return wrapper.Pass(); |
387 AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key); | |
388 string16 comma = ASCIIToUTF16(", "); | |
389 string16 label = profile->GetInfo(NAME_FULL, app_locale) + | |
390 comma + profile->GetInfo(ADDRESS_HOME_LINE1, app_locale); | |
391 string16 address2 = profile->GetInfo(ADDRESS_HOME_LINE2, app_locale); | |
392 if (!address2.empty()) | |
393 label += comma + address2; | |
394 label += ASCIIToUTF16("\n") + | |
395 profile->GetInfo(ADDRESS_HOME_CITY, app_locale) + comma + | |
396 profile->GetInfo(ADDRESS_HOME_STATE, app_locale) + ASCIIToUTF16(" ") + | |
397 profile->GetInfo(ADDRESS_HOME_ZIP, app_locale); | |
398 return label; | |
399 } | 428 } |
400 | 429 |
401 gfx::Image AutofillDialogControllerImpl::SuggestionIconForSection( | 430 gfx::Image AutofillDialogControllerImpl::SuggestionIconForSection( |
402 DialogSection section) { | 431 DialogSection section) { |
403 if (section != SECTION_CC) | 432 if (section != SECTION_CC) |
404 return gfx::Image(); | 433 return gfx::Image(); |
405 | 434 |
406 std::string item_key = | 435 scoped_ptr<DataModelWrapper> model = CreateWrapper(section); |
407 suggested_cc_.GetItemKeyAt(suggested_cc_.checked_item()); | 436 if (!model.get()) |
408 if (item_key.empty()) | |
409 return gfx::Image(); | 437 return gfx::Image(); |
410 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 438 |
411 CreditCard* card = GetManager()->GetCreditCardByGUID(item_key); | 439 return model->GetIcon(); |
412 return rb.GetImageNamed(card->IconResourceId()); | |
413 } | 440 } |
414 | 441 |
415 void AutofillDialogControllerImpl::EditClickedForSection( | 442 void AutofillDialogControllerImpl::EditClickedForSection( |
416 DialogSection section) { | 443 DialogSection section) { |
417 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); | 444 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); |
418 DetailInputs* inputs = MutableRequestedFieldsForSection(section); | 445 DetailInputs* inputs = MutableRequestedFieldsForSection(section); |
419 | 446 |
420 if (section == SECTION_EMAIL) { | 447 if (section == SECTION_EMAIL) { |
421 // TODO(estade): shouldn't need to make this check. | 448 // TODO(estade): shouldn't need to make this check. |
422 if (inputs->empty()) | 449 if (inputs->empty()) |
423 return; | 450 return; |
424 | 451 |
425 (*inputs)[0].autofilled_value = model->GetLabelAt(model->checked_item()); | 452 (*inputs)[0].autofilled_value = model->GetLabelAt(model->checked_item()); |
426 } else { | 453 } else { |
427 std::string guid = model->GetItemKeyAt(model->checked_item()); | 454 scoped_ptr<DataModelWrapper> model = CreateWrapper(section); |
428 DCHECK(!guid.empty()); | 455 model->FillInputs(inputs); |
429 | |
430 FormGroup* form_group = section == SECTION_CC ? | |
431 static_cast<FormGroup*>(GetManager()->GetCreditCardByGUID(guid)) : | |
432 static_cast<FormGroup*>(GetManager()->GetProfileByGUID(guid)); | |
433 DCHECK(form_group); | |
434 FillInputFromFormGroup(form_group, inputs); | |
435 } | 456 } |
436 | 457 |
437 section_editing_state_[section] = true; | 458 section_editing_state_[section] = true; |
438 view_->UpdateSection(section); | 459 view_->UpdateSection(section); |
439 } | 460 } |
440 | 461 |
441 bool AutofillDialogControllerImpl::InputIsValid(AutofillFieldType type, | 462 bool AutofillDialogControllerImpl::InputIsValid(AutofillFieldType type, |
442 const string16& value) { | 463 const string16& value) { |
443 switch (type) { | 464 switch (type) { |
444 case EMAIL_ADDRESS: | 465 case EMAIL_ADDRESS: |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
713 WalletRequestCompleted(true); | 734 WalletRequestCompleted(true); |
714 } | 735 } |
715 | 736 |
716 void AutofillDialogControllerImpl::OnDidGetWalletItems( | 737 void AutofillDialogControllerImpl::OnDidGetWalletItems( |
717 scoped_ptr<wallet::WalletItems> wallet_items) { | 738 scoped_ptr<wallet::WalletItems> wallet_items) { |
718 bool items_changed = !wallet_items_ || *wallet_items != *wallet_items_; | 739 bool items_changed = !wallet_items_ || *wallet_items != *wallet_items_; |
719 wallet_items_ = wallet_items.Pass(); | 740 wallet_items_ = wallet_items.Pass(); |
720 WalletRequestCompleted(true); | 741 WalletRequestCompleted(true); |
721 | 742 |
722 if (items_changed) { | 743 if (items_changed) { |
744 GenerateSuggestionsModels(); | |
745 view_->ModelChanged(); | |
723 view_->UpdateAccountChooser(); | 746 view_->UpdateAccountChooser(); |
724 view_->UpdateNotificationArea(); | 747 view_->UpdateNotificationArea(); |
725 } | 748 } |
726 } | 749 } |
727 | 750 |
728 void AutofillDialogControllerImpl::OnDidSaveAddress( | 751 void AutofillDialogControllerImpl::OnDidSaveAddress( |
729 const std::string& address_id) { | 752 const std::string& address_id) { |
730 NOTIMPLEMENTED() << " address_id=" << address_id; | 753 NOTIMPLEMENTED() << " address_id=" << address_id; |
731 WalletRequestCompleted(true); | 754 WalletRequestCompleted(true); |
732 } | 755 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
823 } | 846 } |
824 | 847 |
825 wallet_client_.GetWalletItems(this); | 848 wallet_client_.GetWalletItems(this); |
826 refresh_wallet_items_queued_ = false; | 849 refresh_wallet_items_queued_ = false; |
827 } | 850 } |
828 | 851 |
829 void AutofillDialogControllerImpl::WalletRequestCompleted(bool success) { | 852 void AutofillDialogControllerImpl::WalletRequestCompleted(bool success) { |
830 if (!success) { | 853 if (!success) { |
831 had_wallet_error_ = true; | 854 had_wallet_error_ = true; |
832 wallet_items_.reset(); | 855 wallet_items_.reset(); |
856 GenerateSuggestionsModels(); | |
857 view_->ModelChanged(); | |
833 view_->UpdateAccountChooser(); | 858 view_->UpdateAccountChooser(); |
834 view_->UpdateNotificationArea(); | 859 view_->UpdateNotificationArea(); |
835 return; | 860 return; |
836 } | 861 } |
837 | 862 |
838 if (refresh_wallet_items_queued_) | 863 if (refresh_wallet_items_queued_) |
839 ScheduleRefreshWalletItems(); | 864 ScheduleRefreshWalletItems(); |
840 } | 865 } |
841 | 866 |
842 void AutofillDialogControllerImpl::GenerateSuggestionsModels() { | 867 void AutofillDialogControllerImpl::GenerateSuggestionsModels() { |
843 suggested_cc_.Reset(); | 868 suggested_cc_.Reset(); |
844 suggested_billing_.Reset(); | 869 suggested_billing_.Reset(); |
845 suggested_email_.Reset(); | 870 suggested_email_.Reset(); |
846 suggested_shipping_.Reset(); | 871 suggested_shipping_.Reset(); |
847 | 872 |
848 PersonalDataManager* manager = GetManager(); | 873 if (CanPayWithWallet()) { |
849 const std::vector<CreditCard*>& cards = manager->credit_cards(); | 874 if (wallet_items_.get()) { |
850 for (size_t i = 0; i < cards.size(); ++i) { | 875 // TODO(estade): seems we need to hardcode the email address. |
851 suggested_cc_.AddKeyedItem(cards[i]->guid(), cards[i]->Label()); | 876 // TODO(estade): CC and billing need to be combined into one section, |
852 } | 877 // and suggestions added here. |
853 | 878 const std::vector<wallet::Address*>& addresses = |
854 const std::vector<AutofillProfile*>& profiles = manager->GetProfiles(); | 879 wallet_items_->addresses(); |
855 const std::string app_locale = AutofillCountry::ApplicationLocale(); | 880 for (size_t i = 0; i < addresses.size(); ++i) { |
856 for (size_t i = 0; i < profiles.size(); ++i) { | 881 suggested_billing_.AddKeyedItem(base::IntToString(i), |
857 if (!IsCompleteProfile(*profiles[i])) | 882 addresses[i]->DisplayName()); |
858 continue; | 883 suggested_shipping_.AddKeyedItem(base::IntToString(i), |
859 | 884 addresses[i]->DisplayName()); |
860 // Add all email addresses. | 885 } |
861 std::vector<string16> values; | 886 } |
862 profiles[i]->GetMultiInfo(EMAIL_ADDRESS, app_locale, &values); | 887 } else { |
863 for (size_t j = 0; j < values.size(); ++j) { | 888 PersonalDataManager* manager = GetManager(); |
864 if (!values[j].empty()) | 889 const std::vector<CreditCard*>& cards = manager->credit_cards(); |
865 suggested_email_.AddKeyedItem(profiles[i]->guid(), values[j]); | 890 for (size_t i = 0; i < cards.size(); ++i) { |
891 suggested_cc_.AddKeyedItem(cards[i]->guid(), cards[i]->Label()); | |
866 } | 892 } |
867 | 893 |
868 // Don't add variants for addresses: the email variants are handled above, | 894 const std::vector<AutofillProfile*>& profiles = manager->GetProfiles(); |
869 // name is part of credit card and we'll just ignore phone number variants. | 895 const std::string app_locale = AutofillCountry::ApplicationLocale(); |
870 suggested_billing_.AddKeyedItem(profiles[i]->guid(), profiles[i]->Label()); | 896 for (size_t i = 0; i < profiles.size(); ++i) { |
871 suggested_shipping_.AddKeyedItem(profiles[i]->guid(), profiles[i]->Label()); | 897 if (!IsCompleteProfile(*profiles[i])) |
898 continue; | |
899 | |
900 // Add all email addresses. | |
901 std::vector<string16> values; | |
902 profiles[i]->GetMultiInfo(EMAIL_ADDRESS, app_locale, &values); | |
903 for (size_t j = 0; j < values.size(); ++j) { | |
904 if (!values[j].empty()) | |
905 suggested_email_.AddKeyedItem(profiles[i]->guid(), values[j]); | |
906 } | |
907 | |
908 // Don't add variants for addresses: the email variants are handled above, | |
909 // name is part of credit card and we'll just ignore phone number | |
910 // variants. | |
911 suggested_billing_.AddKeyedItem(profiles[i]->guid(), | |
912 profiles[i]->Label()); | |
913 suggested_shipping_.AddKeyedItem(profiles[i]->guid(), | |
914 profiles[i]->Label()); | |
915 } | |
872 } | 916 } |
873 | 917 |
874 suggested_email_.AddKeyedItem( | 918 suggested_email_.AddKeyedItem( |
875 std::string(), | 919 std::string(), |
876 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_EMAIL_ADDRESS)); | 920 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_EMAIL_ADDRESS)); |
877 suggested_cc_.AddKeyedItem( | 921 suggested_cc_.AddKeyedItem( |
878 std::string(), | 922 std::string(), |
879 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_CREDIT_CARD)); | 923 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_CREDIT_CARD)); |
880 suggested_billing_.AddKeyedItem( | 924 suggested_billing_.AddKeyedItem( |
881 std::string(), | 925 std::string(), |
(...skipping 13 matching lines...) Expand all Loading... | |
895 } | 939 } |
896 } | 940 } |
897 | 941 |
898 return true; | 942 return true; |
899 } | 943 } |
900 | 944 |
901 void AutofillDialogControllerImpl::FillOutputForSectionWithComparator( | 945 void AutofillDialogControllerImpl::FillOutputForSectionWithComparator( |
902 DialogSection section, | 946 DialogSection section, |
903 const InputFieldComparator& compare) { | 947 const InputFieldComparator& compare) { |
904 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); | 948 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); |
905 std::string guid = model->GetItemKeyAt(model->checked_item()); | 949 std::string item_key = model->GetItemKeyAt(model->checked_item()); |
906 PersonalDataManager* manager = GetManager(); | 950 if (!item_key.empty() && !section_editing_state_[section]) { |
907 if (!guid.empty() && !section_editing_state_[section]) { | 951 scoped_ptr<DataModelWrapper> model = CreateWrapper(section); |
908 FormGroup* form_group = section == SECTION_CC ? | 952 // Only fill in data that is associated with this section. |
909 static_cast<FormGroup*>(manager->GetCreditCardByGUID(guid)) : | 953 const DetailInputs& inputs = RequestedFieldsForSection(section); |
910 static_cast<FormGroup*>(manager->GetProfileByGUID(guid)); | 954 model->FillFormStructure(inputs, compare, &form_structure_); |
911 DCHECK(form_group); | |
912 | |
913 // Calculate the variant by looking at how many items come from the same | |
914 // FormGroup. TODO(estade): add a test for this. | |
915 size_t variant = 0; | |
916 for (int i = model->checked_item() - 1; i >= 0; --i) { | |
917 if (model->GetItemKeyAt(i) == guid) | |
918 variant++; | |
919 else | |
920 break; | |
921 } | |
922 | |
923 FillFormStructureForSection(*form_group, variant, section, compare); | |
924 | 955 |
925 // CVC needs special-casing because the CreditCard class doesn't store | 956 // CVC needs special-casing because the CreditCard class doesn't store |
926 // or handle them. | 957 // or handle them. |
927 if (section == SECTION_CC) | 958 if (section == SECTION_CC) |
928 SetCvcResult(view_->GetCvc()); | 959 SetCvcResult(view_->GetCvc()); |
929 } else { | 960 } else { |
930 // The user manually input data. | 961 // The user manually input data. |
962 PersonalDataManager* manager = GetManager(); | |
931 DetailOutputMap output; | 963 DetailOutputMap output; |
932 view_->GetUserInput(section, &output); | 964 view_->GetUserInput(section, &output); |
933 | 965 |
934 // Save the info as new or edited data, then fill it into |form_structure_|. | 966 // Save the info as new or edited data, then fill it into |form_structure_|. |
935 if (section == SECTION_CC) { | 967 if (section == SECTION_CC) { |
936 CreditCard card; | 968 CreditCard card; |
937 FillFormGroupFromOutputs(output, &card); | 969 FillFormGroupFromOutputs(output, &card); |
938 if (view_->SaveDetailsLocally()) | 970 if (view_->SaveDetailsLocally()) |
939 manager->SaveImportedCreditCard(card); | 971 manager->SaveImportedCreditCard(card); |
940 FillFormStructureForSection(card, 0, section, compare); | 972 FillFormStructureForSection(card, 0, section, compare); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1033 DialogSection section) { | 1065 DialogSection section) { |
1034 return const_cast<DetailInputs*>(&RequestedFieldsForSection(section)); | 1066 return const_cast<DetailInputs*>(&RequestedFieldsForSection(section)); |
1035 } | 1067 } |
1036 | 1068 |
1037 void AutofillDialogControllerImpl::HidePopup() { | 1069 void AutofillDialogControllerImpl::HidePopup() { |
1038 if (popup_controller_) | 1070 if (popup_controller_) |
1039 popup_controller_->Hide(); | 1071 popup_controller_->Hide(); |
1040 } | 1072 } |
1041 | 1073 |
1042 } // namespace autofill | 1074 } // namespace autofill |
OLD | NEW |