| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 // Equivalent billing field type is used to support UseBillingAsShipping | 149 // Equivalent billing field type is used to support UseBillingAsShipping |
| 150 // usecase. | 150 // usecase. |
| 151 ServerFieldType field_type = | 151 ServerFieldType field_type = |
| 152 AutofillType::GetEquivalentBillingFieldType( | 152 AutofillType::GetEquivalentBillingFieldType( |
| 153 field.Type().GetStorableType()); | 153 field.Type().GetStorableType()); |
| 154 | 154 |
| 155 return common::InputTypeMatchesFieldType(input, AutofillType(field_type)); | 155 return common::InputTypeMatchesFieldType(input, AutofillType(field_type)); |
| 156 } | 156 } |
| 157 | 157 |
| 158 // Initializes |form_group| from user-entered data. | 158 // Initializes |form_group| from user-entered data. |
| 159 void FillFormGroupFromOutputs(const DetailOutputMap& detail_outputs, | 159 void FillFormGroupFromOutputs(const FieldValueMap& detail_outputs, |
| 160 FormGroup* form_group) { | 160 FormGroup* form_group) { |
| 161 for (DetailOutputMap::const_iterator iter = detail_outputs.begin(); | 161 for (FieldValueMap::const_iterator iter = detail_outputs.begin(); |
| 162 iter != detail_outputs.end(); ++iter) { | 162 iter != detail_outputs.end(); ++iter) { |
| 163 ServerFieldType type = iter->first->type; | 163 ServerFieldType type = iter->first; |
| 164 if (!iter->second.empty()) { | 164 if (!iter->second.empty()) { |
| 165 if (type == ADDRESS_HOME_COUNTRY || type == ADDRESS_BILLING_COUNTRY) { | 165 if (type == ADDRESS_HOME_COUNTRY || type == ADDRESS_BILLING_COUNTRY) { |
| 166 form_group->SetInfo(AutofillType(type), | 166 form_group->SetInfo(AutofillType(type), |
| 167 iter->second, | 167 iter->second, |
| 168 g_browser_process->GetApplicationLocale()); | 168 g_browser_process->GetApplicationLocale()); |
| 169 } else { | 169 } else { |
| 170 form_group->SetRawInfo( | 170 form_group->SetRawInfo( |
| 171 AutofillType(type).GetStorableType(), iter->second); | 171 AutofillType(type).GetStorableType(), iter->second); |
| 172 } | 172 } |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 } | 175 } |
| 176 | 176 |
| 177 // Get billing info from |output| and put it into |card|, |cvc|, and |profile|. | 177 // Get billing info from |output| and put it into |card|, |cvc|, and |profile|. |
| 178 // These outparams are required because |card|/|profile| accept different types | 178 // These outparams are required because |card|/|profile| accept different types |
| 179 // of raw info, and CreditCard doesn't save CVCs. | 179 // of raw info, and CreditCard doesn't save CVCs. |
| 180 void GetBillingInfoFromOutputs(const DetailOutputMap& output, | 180 void GetBillingInfoFromOutputs(const FieldValueMap& output, |
| 181 CreditCard* card, | 181 CreditCard* card, |
| 182 string16* cvc, | 182 base::string16* cvc, |
| 183 AutofillProfile* profile) { | 183 AutofillProfile* profile) { |
| 184 for (DetailOutputMap::const_iterator it = output.begin(); | 184 for (FieldValueMap::const_iterator it = output.begin(); |
| 185 it != output.end(); ++it) { | 185 it != output.end(); ++it) { |
| 186 string16 trimmed; | 186 const ServerFieldType type = it->first; |
| 187 base::string16 trimmed; |
| 187 TrimWhitespace(it->second, TRIM_ALL, &trimmed); | 188 TrimWhitespace(it->second, TRIM_ALL, &trimmed); |
| 188 | 189 |
| 189 // Special case CVC as CreditCard just swallows it. | 190 // Special case CVC as CreditCard just swallows it. |
| 190 if (it->first->type == CREDIT_CARD_VERIFICATION_CODE) { | 191 if (type == CREDIT_CARD_VERIFICATION_CODE) { |
| 191 if (cvc) | 192 if (cvc) |
| 192 cvc->assign(trimmed); | 193 cvc->assign(trimmed); |
| 193 } else if (it->first->type == ADDRESS_HOME_COUNTRY || | 194 } else if (type == ADDRESS_HOME_COUNTRY || |
| 194 it->first->type == ADDRESS_BILLING_COUNTRY) { | 195 type == ADDRESS_BILLING_COUNTRY) { |
| 195 if (profile) { | 196 if (profile) { |
| 196 profile->SetInfo(AutofillType(it->first->type), | 197 profile->SetInfo(AutofillType(type), |
| 197 trimmed, | 198 trimmed, |
| 198 g_browser_process->GetApplicationLocale()); | 199 g_browser_process->GetApplicationLocale()); |
| 199 } | 200 } |
| 200 } else { | 201 } else { |
| 201 // Copy the credit card name to |profile| in addition to |card| as | 202 // Copy the credit card name to |profile| in addition to |card| as |
| 202 // wallet::Instrument requires a recipient name for its billing address. | 203 // wallet::Instrument requires a recipient name for its billing address. |
| 203 if (card && it->first->type == NAME_FULL) | 204 if (card && type == NAME_FULL) |
| 204 card->SetRawInfo(CREDIT_CARD_NAME, trimmed); | 205 card->SetRawInfo(CREDIT_CARD_NAME, trimmed); |
| 205 | 206 |
| 206 if (common::IsCreditCardType(it->first->type)) { | 207 if (common::IsCreditCardType(type)) { |
| 207 if (card) | 208 if (card) |
| 208 card->SetRawInfo(it->first->type, trimmed); | 209 card->SetRawInfo(type, trimmed); |
| 209 } else if (profile) { | 210 } else if (profile) { |
| 210 profile->SetRawInfo( | 211 profile->SetRawInfo(AutofillType(type).GetStorableType(), trimmed); |
| 211 AutofillType(it->first->type).GetStorableType(), trimmed); | |
| 212 } | 212 } |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 } | 215 } |
| 216 | 216 |
| 217 // Returns the containing window for the given |web_contents|. The containing | 217 // Returns the containing window for the given |web_contents|. The containing |
| 218 // window might be a browser window for a Chrome tab, or it might be a shell | 218 // window might be a browser window for a Chrome tab, or it might be a shell |
| 219 // window for a platform app. | 219 // window for a platform app. |
| 220 ui::BaseWindow* GetBaseWindowForWebContents( | 220 ui::BaseWindow* GetBaseWindowForWebContents( |
| 221 const content::WebContents* web_contents) { | 221 const content::WebContents* web_contents) { |
| 222 Browser* browser = chrome::FindBrowserWithWebContents(web_contents); | 222 Browser* browser = chrome::FindBrowserWithWebContents(web_contents); |
| 223 if (browser) | 223 if (browser) |
| 224 return browser->window(); | 224 return browser->window(); |
| 225 | 225 |
| 226 gfx::NativeWindow native_window = | 226 gfx::NativeWindow native_window = |
| 227 web_contents->GetView()->GetTopLevelNativeWindow(); | 227 web_contents->GetView()->GetTopLevelNativeWindow(); |
| 228 apps::ShellWindow* shell_window = | 228 apps::ShellWindow* shell_window = |
| 229 apps::ShellWindowRegistry:: | 229 apps::ShellWindowRegistry:: |
| 230 GetShellWindowForNativeWindowAnyProfile(native_window); | 230 GetShellWindowForNativeWindowAnyProfile(native_window); |
| 231 return shell_window->GetBaseWindow(); | 231 return shell_window->GetBaseWindow(); |
| 232 } | 232 } |
| 233 | 233 |
| 234 // Extracts the string value of a field with |type| from |output|. This is | |
| 235 // useful when you only need the value of 1 input from a section of view inputs. | |
| 236 string16 GetValueForType(const DetailOutputMap& output, | |
| 237 ServerFieldType type) { | |
| 238 for (DetailOutputMap::const_iterator it = output.begin(); | |
| 239 it != output.end(); ++it) { | |
| 240 if (it->first->type == type) | |
| 241 return it->second; | |
| 242 } | |
| 243 return string16(); | |
| 244 } | |
| 245 | |
| 246 // Returns a string descriptor for a DialogSection, for use with prefs (do not | 234 // Returns a string descriptor for a DialogSection, for use with prefs (do not |
| 247 // change these values). | 235 // change these values). |
| 248 std::string SectionToPrefString(DialogSection section) { | 236 std::string SectionToPrefString(DialogSection section) { |
| 249 switch (section) { | 237 switch (section) { |
| 250 case SECTION_CC: | 238 case SECTION_CC: |
| 251 return "cc"; | 239 return "cc"; |
| 252 | 240 |
| 253 case SECTION_BILLING: | 241 case SECTION_BILLING: |
| 254 return "billing"; | 242 return "billing"; |
| 255 | 243 |
| (...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 return false; | 1121 return false; |
| 1134 | 1122 |
| 1135 // If this is a combobox at the default value, don't preserve it. | 1123 // If this is a combobox at the default value, don't preserve it. |
| 1136 ui::ComboboxModel* model = ComboboxModelForAutofillType(type); | 1124 ui::ComboboxModel* model = ComboboxModelForAutofillType(type); |
| 1137 if (model && model->GetItemAt(model->GetDefaultIndex()) == value) | 1125 if (model && model->GetItemAt(model->GetDefaultIndex()) == value) |
| 1138 return false; | 1126 return false; |
| 1139 | 1127 |
| 1140 return true; | 1128 return true; |
| 1141 } | 1129 } |
| 1142 | 1130 |
| 1143 DetailOutputMap AutofillDialogControllerImpl::TakeUserInputSnapshot() { | 1131 FieldValueMap AutofillDialogControllerImpl::TakeUserInputSnapshot() { |
| 1144 DetailOutputMap snapshot; | 1132 FieldValueMap snapshot; |
| 1145 if (!view_) | 1133 if (!view_) |
| 1146 return snapshot; | 1134 return snapshot; |
| 1147 | 1135 |
| 1148 for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) { | 1136 for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) { |
| 1149 DialogSection section = static_cast<DialogSection>(i); | 1137 DialogSection section = static_cast<DialogSection>(i); |
| 1150 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); | 1138 SuggestionsMenuModel* model = SuggestionsMenuModelForSection(section); |
| 1151 if (model->GetItemKeyForCheckedItem() != kAddNewItemKey) | 1139 if (model->GetItemKeyForCheckedItem() != kAddNewItemKey) |
| 1152 continue; | 1140 continue; |
| 1153 | 1141 |
| 1154 DetailOutputMap outputs; | 1142 FieldValueMap outputs; |
| 1155 view_->GetUserInput(section, &outputs); | 1143 view_->GetUserInput(section, &outputs); |
| 1156 // Remove fields that are empty, at their default values, or invalid. | 1144 // Remove fields that are empty, at their default values, or invalid. |
| 1157 for (DetailOutputMap::iterator it = outputs.begin(); it != outputs.end(); | 1145 for (FieldValueMap::iterator it = outputs.begin(); it != outputs.end(); |
| 1158 ++it) { | 1146 ++it) { |
| 1159 if (InputWasEdited(it->first->type, it->second) && | 1147 if (InputWasEdited(it->first, it->second) && |
| 1160 InputValidityMessage(section, it->first->type, it->second).empty()) { | 1148 InputValidityMessage(section, it->first, it->second).empty()) { |
| 1161 snapshot.insert(std::make_pair(it->first, it->second)); | 1149 snapshot.insert(std::make_pair(it->first, it->second)); |
| 1162 } | 1150 } |
| 1163 } | 1151 } |
| 1164 } | 1152 } |
| 1165 | 1153 |
| 1166 return snapshot; | 1154 return snapshot; |
| 1167 } | 1155 } |
| 1168 | 1156 |
| 1169 void AutofillDialogControllerImpl::RestoreUserInputFromSnapshot( | 1157 void AutofillDialogControllerImpl::RestoreUserInputFromSnapshot( |
| 1170 const DetailOutputMap& snapshot) { | 1158 const FieldValueMap& snapshot) { |
| 1171 if (snapshot.empty()) | 1159 if (snapshot.empty()) |
| 1172 return; | 1160 return; |
| 1173 | 1161 |
| 1174 DetailOutputWrapper wrapper(snapshot); | 1162 FieldMapWrapper wrapper(snapshot); |
| 1175 for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) { | 1163 for (size_t i = SECTION_MIN; i <= SECTION_MAX; ++i) { |
| 1176 DialogSection section = static_cast<DialogSection>(i); | 1164 DialogSection section = static_cast<DialogSection>(i); |
| 1177 if (!SectionIsActive(section)) | 1165 if (!SectionIsActive(section)) |
| 1178 continue; | 1166 continue; |
| 1179 | 1167 |
| 1180 DetailInputs* inputs = MutableRequestedFieldsForSection(section); | 1168 DetailInputs* inputs = MutableRequestedFieldsForSection(section); |
| 1181 wrapper.FillInputs(inputs); | 1169 wrapper.FillInputs(inputs); |
| 1182 | 1170 |
| 1183 for (size_t i = 0; i < inputs->size(); ++i) { | 1171 for (size_t i = 0; i < inputs->size(); ++i) { |
| 1184 if (InputWasEdited((*inputs)[i].type, (*inputs)[i].initial_value)) { | 1172 if (InputWasEdited((*inputs)[i].type, (*inputs)[i].initial_value)) { |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 } | 1413 } |
| 1426 | 1414 |
| 1427 string16 AutofillDialogControllerImpl::RequiredActionTextForSection( | 1415 string16 AutofillDialogControllerImpl::RequiredActionTextForSection( |
| 1428 DialogSection section) const { | 1416 DialogSection section) const { |
| 1429 if (section == SECTION_CC_BILLING && IsSubmitPausedOn(wallet::VERIFY_CVV)) { | 1417 if (section == SECTION_CC_BILLING && IsSubmitPausedOn(wallet::VERIFY_CVV)) { |
| 1430 const wallet::WalletItems::MaskedInstrument* current_instrument = | 1418 const wallet::WalletItems::MaskedInstrument* current_instrument = |
| 1431 wallet_items_->GetInstrumentById(active_instrument_id_); | 1419 wallet_items_->GetInstrumentById(active_instrument_id_); |
| 1432 if (current_instrument) | 1420 if (current_instrument) |
| 1433 return current_instrument->TypeAndLastFourDigits(); | 1421 return current_instrument->TypeAndLastFourDigits(); |
| 1434 | 1422 |
| 1435 DetailOutputMap output; | 1423 FieldValueMap output; |
| 1436 view_->GetUserInput(section, &output); | 1424 view_->GetUserInput(section, &output); |
| 1437 CreditCard card; | 1425 CreditCard card; |
| 1438 GetBillingInfoFromOutputs(output, &card, NULL, NULL); | 1426 GetBillingInfoFromOutputs(output, &card, NULL, NULL); |
| 1439 return card.TypeAndLastFourDigits(); | 1427 return card.TypeAndLastFourDigits(); |
| 1440 } | 1428 } |
| 1441 | 1429 |
| 1442 return string16(); | 1430 return string16(); |
| 1443 } | 1431 } |
| 1444 | 1432 |
| 1445 string16 AutofillDialogControllerImpl::ExtraSuggestionTextForSection( | 1433 string16 AutofillDialogControllerImpl::ExtraSuggestionTextForSection( |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1608 if (section != SECTION_CC_BILLING) | 1596 if (section != SECTION_CC_BILLING) |
| 1609 return true; | 1597 return true; |
| 1610 | 1598 |
| 1611 if (input.type == CREDIT_CARD_NUMBER) | 1599 if (input.type == CREDIT_CARD_NUMBER) |
| 1612 return !IsEditingExistingData(section); | 1600 return !IsEditingExistingData(section); |
| 1613 | 1601 |
| 1614 // For CVC, only require (allow) input if the user has edited some other | 1602 // For CVC, only require (allow) input if the user has edited some other |
| 1615 // aspect of the card. | 1603 // aspect of the card. |
| 1616 if (input.type == CREDIT_CARD_VERIFICATION_CODE && | 1604 if (input.type == CREDIT_CARD_VERIFICATION_CODE && |
| 1617 IsEditingExistingData(section)) { | 1605 IsEditingExistingData(section)) { |
| 1618 DetailOutputMap output; | 1606 FieldValueMap output; |
| 1619 view_->GetUserInput(section, &output); | 1607 view_->GetUserInput(section, &output); |
| 1620 WalletInstrumentWrapper wrapper(ActiveInstrument()); | 1608 WalletInstrumentWrapper wrapper(ActiveInstrument()); |
| 1621 | 1609 |
| 1622 for (DetailOutputMap::iterator iter = output.begin(); iter != output.end(); | 1610 for (FieldValueMap::iterator iter = output.begin(); iter != output.end(); |
| 1623 ++iter) { | 1611 ++iter) { |
| 1624 if (iter->first->type == input.type) | 1612 if (iter->first == input.type) |
| 1625 continue; | 1613 continue; |
| 1626 | 1614 |
| 1627 AutofillType type(iter->first->type); | 1615 AutofillType type(iter->first); |
| 1628 if (type.group() == CREDIT_CARD && | 1616 if (type.group() == CREDIT_CARD && |
| 1629 iter->second != wrapper.GetInfo(type)) { | 1617 iter->second != wrapper.GetInfo(type)) { |
| 1630 return true; | 1618 return true; |
| 1631 } | 1619 } |
| 1632 } | 1620 } |
| 1633 | 1621 |
| 1634 return false; | 1622 return false; |
| 1635 } | 1623 } |
| 1636 | 1624 |
| 1637 return true; | 1625 return true; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1739 } | 1727 } |
| 1740 | 1728 |
| 1741 return value.empty() ? | 1729 return value.empty() ? |
| 1742 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_VALIDATION_MISSING_VALUE) : | 1730 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_VALIDATION_MISSING_VALUE) : |
| 1743 base::string16(); | 1731 base::string16(); |
| 1744 } | 1732 } |
| 1745 | 1733 |
| 1746 // TODO(groby): Also add tests. | 1734 // TODO(groby): Also add tests. |
| 1747 ValidityMessages AutofillDialogControllerImpl::InputsAreValid( | 1735 ValidityMessages AutofillDialogControllerImpl::InputsAreValid( |
| 1748 DialogSection section, | 1736 DialogSection section, |
| 1749 const DetailOutputMap& inputs) { | 1737 const FieldValueMap& inputs) { |
| 1750 ValidityMessages messages; | 1738 ValidityMessages messages; |
| 1751 std::map<ServerFieldType, string16> field_values; | 1739 std::map<ServerFieldType, string16> field_values; |
| 1752 for (DetailOutputMap::const_iterator iter = inputs.begin(); | 1740 for (FieldValueMap::const_iterator iter = inputs.begin(); |
| 1753 iter != inputs.end(); ++iter) { | 1741 iter != inputs.end(); ++iter) { |
| 1754 const ServerFieldType type = iter->first->type; | 1742 const ServerFieldType type = iter->first; |
| 1755 | 1743 |
| 1756 base::string16 text = InputValidityMessage(section, type, iter->second); | 1744 base::string16 text = InputValidityMessage(section, type, iter->second); |
| 1757 | 1745 |
| 1758 // Skip empty/unchanged fields in edit mode. Ignore country code as it | 1746 // Skip empty/unchanged fields in edit mode. Ignore country code as it |
| 1759 // always has a value. If the individual field does not have validation | 1747 // always has a value. If the individual field does not have validation |
| 1760 // errors, assume it to be valid unless later proven otherwise. | 1748 // errors, assume it to be valid unless later proven otherwise. |
| 1761 bool sure = InputWasEdited(type, iter->second) || | 1749 bool sure = InputWasEdited(type, iter->second) || |
| 1762 ComboboxModelForAutofillType(type) == &country_combobox_model_; | 1750 ComboboxModelForAutofillType(type) == &country_combobox_model_; |
| 1763 | 1751 |
| 1764 // Consider only individually valid fields for inter-field validation. | 1752 // Consider only individually valid fields for inter-field validation. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1842 IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_PHONE_NUMBER); | 1830 IDS_AUTOFILL_DIALOG_VALIDATION_INVALID_PHONE_NUMBER); |
| 1843 } | 1831 } |
| 1844 messages.Set(PHONE_BILLING_WHOLE_NUMBER, phone_message); | 1832 messages.Set(PHONE_BILLING_WHOLE_NUMBER, phone_message); |
| 1845 } | 1833 } |
| 1846 | 1834 |
| 1847 return messages; | 1835 return messages; |
| 1848 } | 1836 } |
| 1849 | 1837 |
| 1850 void AutofillDialogControllerImpl::UserEditedOrActivatedInput( | 1838 void AutofillDialogControllerImpl::UserEditedOrActivatedInput( |
| 1851 DialogSection section, | 1839 DialogSection section, |
| 1852 const DetailInput* input, | 1840 ServerFieldType type, |
| 1853 gfx::NativeView parent_view, | 1841 gfx::NativeView parent_view, |
| 1854 const gfx::Rect& content_bounds, | 1842 const gfx::Rect& content_bounds, |
| 1855 const string16& field_contents, | 1843 const string16& field_contents, |
| 1856 bool was_edit) { | 1844 bool was_edit) { |
| 1857 // If the field is edited down to empty, don't show a popup. | 1845 // If the field is edited down to empty, don't show a popup. |
| 1858 if (was_edit && field_contents.empty()) { | 1846 if (was_edit && field_contents.empty()) { |
| 1859 HidePopup(); | 1847 HidePopup(); |
| 1860 return; | 1848 return; |
| 1861 } | 1849 } |
| 1862 | 1850 |
| 1863 // If the user clicks while the popup is already showing, be sure to hide | 1851 // If the user clicks while the popup is already showing, be sure to hide |
| 1864 // it. | 1852 // it. |
| 1865 if (!was_edit && popup_controller_.get()) { | 1853 if (!was_edit && popup_controller_.get()) { |
| 1866 HidePopup(); | 1854 HidePopup(); |
| 1867 return; | 1855 return; |
| 1868 } | 1856 } |
| 1869 | 1857 |
| 1870 std::vector<string16> popup_values, popup_labels, popup_icons; | 1858 std::vector<string16> popup_values, popup_labels, popup_icons; |
| 1871 if (common::IsCreditCardType(input->type)) { | 1859 if (common::IsCreditCardType(type)) { |
| 1872 GetManager()->GetCreditCardSuggestions(AutofillType(input->type), | 1860 GetManager()->GetCreditCardSuggestions(AutofillType(type), |
| 1873 field_contents, | 1861 field_contents, |
| 1874 &popup_values, | 1862 &popup_values, |
| 1875 &popup_labels, | 1863 &popup_labels, |
| 1876 &popup_icons, | 1864 &popup_icons, |
| 1877 &popup_guids_); | 1865 &popup_guids_); |
| 1878 } else { | 1866 } else { |
| 1879 std::vector<ServerFieldType> field_types; | 1867 std::vector<ServerFieldType> field_types; |
| 1880 const DetailInputs& inputs = RequestedFieldsForSection(section); | 1868 const DetailInputs& inputs = RequestedFieldsForSection(section); |
| 1881 for (DetailInputs::const_iterator iter = inputs.begin(); | 1869 for (DetailInputs::const_iterator iter = inputs.begin(); |
| 1882 iter != inputs.end(); ++iter) { | 1870 iter != inputs.end(); ++iter) { |
| 1883 field_types.push_back(iter->type); | 1871 field_types.push_back(iter->type); |
| 1884 } | 1872 } |
| 1885 GetManager()->GetProfileSuggestions(AutofillType(input->type), | 1873 GetManager()->GetProfileSuggestions(AutofillType(type), |
| 1886 field_contents, | 1874 field_contents, |
| 1887 false, | 1875 false, |
| 1888 field_types, | 1876 field_types, |
| 1889 &popup_values, | 1877 &popup_values, |
| 1890 &popup_labels, | 1878 &popup_labels, |
| 1891 &popup_icons, | 1879 &popup_icons, |
| 1892 &popup_guids_); | 1880 &popup_guids_); |
| 1893 } | 1881 } |
| 1894 | 1882 |
| 1895 if (popup_values.empty()) { | 1883 if (popup_values.empty()) { |
| 1896 HidePopup(); | 1884 HidePopup(); |
| 1897 return; | 1885 return; |
| 1898 } | 1886 } |
| 1899 | 1887 |
| 1888 // |input_showing_popup_| must be set before calling |Show()|. |
| 1889 const DetailInputs& inputs = RequestedFieldsForSection(section); |
| 1890 for (DetailInputs::const_iterator iter = inputs.begin(); |
| 1891 iter != inputs.end(); ++iter) { |
| 1892 if (iter->type == type) { |
| 1893 input_showing_popup_ = &(*iter); |
| 1894 break; |
| 1895 } |
| 1896 } |
| 1897 |
| 1898 if (!input_showing_popup_) |
| 1899 return; |
| 1900 |
| 1900 // TODO(estade): do we need separators and control rows like 'Clear | 1901 // TODO(estade): do we need separators and control rows like 'Clear |
| 1901 // Form'? | 1902 // Form'? |
| 1902 std::vector<int> popup_ids; | 1903 std::vector<int> popup_ids; |
| 1903 for (size_t i = 0; i < popup_guids_.size(); ++i) { | 1904 for (size_t i = 0; i < popup_guids_.size(); ++i) { |
| 1904 popup_ids.push_back(i); | 1905 popup_ids.push_back(i); |
| 1905 } | 1906 } |
| 1906 | 1907 |
| 1907 popup_controller_ = AutofillPopupControllerImpl::GetOrCreate( | 1908 popup_controller_ = AutofillPopupControllerImpl::GetOrCreate( |
| 1908 popup_controller_, | 1909 popup_controller_, |
| 1909 weak_ptr_factory_.GetWeakPtr(), | 1910 weak_ptr_factory_.GetWeakPtr(), |
| 1910 NULL, | 1911 NULL, |
| 1911 parent_view, | 1912 parent_view, |
| 1912 content_bounds, | 1913 content_bounds, |
| 1913 base::i18n::IsRTL() ? | 1914 base::i18n::IsRTL() ? |
| 1914 base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT); | 1915 base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT); |
| 1915 popup_controller_->set_hide_on_outside_click(true); | 1916 popup_controller_->set_hide_on_outside_click(true); |
| 1916 | |
| 1917 // |input_showing_popup_| must be set before calling |Show()|. | |
| 1918 input_showing_popup_ = input; | |
| 1919 | |
| 1920 popup_controller_->Show(popup_values, | 1917 popup_controller_->Show(popup_values, |
| 1921 popup_labels, | 1918 popup_labels, |
| 1922 popup_icons, | 1919 popup_icons, |
| 1923 popup_ids); | 1920 popup_ids); |
| 1924 } | 1921 } |
| 1925 | 1922 |
| 1926 void AutofillDialogControllerImpl::FocusMoved() { | 1923 void AutofillDialogControllerImpl::FocusMoved() { |
| 1927 HidePopup(); | 1924 HidePopup(); |
| 1928 } | 1925 } |
| 1929 | 1926 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2080 // name. | 2077 // name. |
| 2081 if (!IsSubmitPausedOn(wallet::VERIFY_CVV)) { | 2078 if (!IsSubmitPausedOn(wallet::VERIFY_CVV)) { |
| 2082 submitted_cardholder_name_ = | 2079 submitted_cardholder_name_ = |
| 2083 GetValueFromSection(SECTION_CC_BILLING, NAME_BILLING_FULL); | 2080 GetValueFromSection(SECTION_CC_BILLING, NAME_BILLING_FULL); |
| 2084 | 2081 |
| 2085 // Snag the last four digits of the backing card now as it could be wiped | 2082 // Snag the last four digits of the backing card now as it could be wiped |
| 2086 // out if a CVC challenge happens. | 2083 // out if a CVC challenge happens. |
| 2087 if (ActiveInstrument()) { | 2084 if (ActiveInstrument()) { |
| 2088 backing_card_last_four_ = ActiveInstrument()->TypeAndLastFourDigits(); | 2085 backing_card_last_four_ = ActiveInstrument()->TypeAndLastFourDigits(); |
| 2089 } else { | 2086 } else { |
| 2090 DetailOutputMap output; | 2087 FieldValueMap output; |
| 2091 view_->GetUserInput(SECTION_CC_BILLING, &output); | 2088 view_->GetUserInput(SECTION_CC_BILLING, &output); |
| 2092 CreditCard card; | 2089 CreditCard card; |
| 2093 GetBillingInfoFromOutputs(output, &card, NULL, NULL); | 2090 GetBillingInfoFromOutputs(output, &card, NULL, NULL); |
| 2094 backing_card_last_four_ = card.TypeAndLastFourDigits(); | 2091 backing_card_last_four_ = card.TypeAndLastFourDigits(); |
| 2095 } | 2092 } |
| 2096 } | 2093 } |
| 2097 DCHECK(!submitted_cardholder_name_.empty()); | 2094 DCHECK(!submitted_cardholder_name_.empty()); |
| 2098 DCHECK(!backing_card_last_four_.empty()); | 2095 DCHECK(!backing_card_last_four_.empty()); |
| 2099 } | 2096 } |
| 2100 | 2097 |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2637 wallet_errors_.clear(); | 2634 wallet_errors_.clear(); |
| 2638 GetWalletClient()->CancelRequests(); | 2635 GetWalletClient()->CancelRequests(); |
| 2639 SetIsSubmitting(false); | 2636 SetIsSubmitting(false); |
| 2640 wallet_error_notification_ = GetWalletError(error_type); | 2637 wallet_error_notification_ = GetWalletError(error_type); |
| 2641 account_chooser_model_.SetHadWalletError(); | 2638 account_chooser_model_.SetHadWalletError(); |
| 2642 } | 2639 } |
| 2643 | 2640 |
| 2644 void AutofillDialogControllerImpl::SuggestionsUpdated() { | 2641 void AutofillDialogControllerImpl::SuggestionsUpdated() { |
| 2645 ScopedViewUpdates updates(view_.get()); | 2642 ScopedViewUpdates updates(view_.get()); |
| 2646 | 2643 |
| 2647 const DetailOutputMap snapshot = TakeUserInputSnapshot(); | 2644 const FieldValueMap snapshot = TakeUserInputSnapshot(); |
| 2648 | 2645 |
| 2649 suggested_cc_.Reset(); | 2646 suggested_cc_.Reset(); |
| 2650 suggested_billing_.Reset(); | 2647 suggested_billing_.Reset(); |
| 2651 suggested_cc_billing_.Reset(); | 2648 suggested_cc_billing_.Reset(); |
| 2652 suggested_shipping_.Reset(); | 2649 suggested_shipping_.Reset(); |
| 2653 HidePopup(); | 2650 HidePopup(); |
| 2654 | 2651 |
| 2655 suggested_shipping_.AddKeyedItem( | 2652 suggested_shipping_.AddKeyedItem( |
| 2656 kSameAsBillingKey, | 2653 kSameAsBillingKey, |
| 2657 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_USE_BILLING_FOR_SHIPPING)); | 2654 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_USE_BILLING_FOR_SHIPPING)); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2853 // When filling from Wallet data, use the email address associated with the | 2850 // When filling from Wallet data, use the email address associated with the |
| 2854 // account. There is no other email address stored as part of a Wallet | 2851 // account. There is no other email address stored as part of a Wallet |
| 2855 // address. | 2852 // address. |
| 2856 if (section == SECTION_CC_BILLING) { | 2853 if (section == SECTION_CC_BILLING) { |
| 2857 SetOutputForFieldsOfType( | 2854 SetOutputForFieldsOfType( |
| 2858 EMAIL_ADDRESS, account_chooser_model_.GetActiveWalletAccountName()); | 2855 EMAIL_ADDRESS, account_chooser_model_.GetActiveWalletAccountName()); |
| 2859 } | 2856 } |
| 2860 } else { | 2857 } else { |
| 2861 // The user manually input data. If using Autofill, save the info as new or | 2858 // The user manually input data. If using Autofill, save the info as new or |
| 2862 // edited data. Always fill local data into |form_structure_|. | 2859 // edited data. Always fill local data into |form_structure_|. |
| 2863 DetailOutputMap output; | 2860 FieldValueMap output; |
| 2864 view_->GetUserInput(section, &output); | 2861 view_->GetUserInput(section, &output); |
| 2865 | 2862 |
| 2866 if (section == SECTION_CC) { | 2863 if (section == SECTION_CC) { |
| 2867 CreditCard card; | 2864 CreditCard card; |
| 2868 card.set_origin(kAutofillDialogOrigin); | 2865 card.set_origin(kAutofillDialogOrigin); |
| 2869 FillFormGroupFromOutputs(output, &card); | 2866 FillFormGroupFromOutputs(output, &card); |
| 2870 | 2867 |
| 2871 // The card holder name comes from the billing address section. | 2868 // The card holder name comes from the billing address section. |
| 2872 card.SetRawInfo(CREDIT_CARD_NAME, | 2869 card.SetRawInfo(CREDIT_CARD_NAME, |
| 2873 GetValueFromSection(SECTION_BILLING, NAME_BILLING_FULL)); | 2870 GetValueFromSection(SECTION_BILLING, NAME_BILLING_FULL)); |
| 2874 | 2871 |
| 2875 if (ShouldSaveDetailsLocally()) { | 2872 if (ShouldSaveDetailsLocally()) { |
| 2876 std::string guid = GetManager()->SaveImportedCreditCard(card); | 2873 std::string guid = GetManager()->SaveImportedCreditCard(card); |
| 2877 newly_saved_data_model_guids_[section] = guid; | 2874 newly_saved_data_model_guids_[section] = guid; |
| 2878 DCHECK(!profile()->IsOffTheRecord()); | 2875 DCHECK(!profile()->IsOffTheRecord()); |
| 2879 newly_saved_card_.reset(new CreditCard(card)); | 2876 newly_saved_card_.reset(new CreditCard(card)); |
| 2880 } | 2877 } |
| 2881 | 2878 |
| 2882 AutofillCreditCardWrapper card_wrapper(&card); | 2879 AutofillCreditCardWrapper card_wrapper(&card); |
| 2883 card_wrapper.FillFormStructure(inputs, compare, &form_structure_); | 2880 card_wrapper.FillFormStructure(inputs, compare, &form_structure_); |
| 2884 | 2881 |
| 2885 // Again, CVC needs special-casing. Fill it in directly from |output|. | 2882 // Again, CVC needs special-casing. Fill it in directly from |output|. |
| 2886 SetOutputForFieldsOfType( | 2883 SetOutputForFieldsOfType( |
| 2887 CREDIT_CARD_VERIFICATION_CODE, | 2884 CREDIT_CARD_VERIFICATION_CODE, |
| 2888 GetValueForType(output, CREDIT_CARD_VERIFICATION_CODE)); | 2885 output[CREDIT_CARD_VERIFICATION_CODE]); |
| 2889 } else { | 2886 } else { |
| 2890 AutofillProfile profile; | 2887 AutofillProfile profile; |
| 2891 profile.set_origin(kAutofillDialogOrigin); | 2888 profile.set_origin(kAutofillDialogOrigin); |
| 2892 FillFormGroupFromOutputs(output, &profile); | 2889 FillFormGroupFromOutputs(output, &profile); |
| 2893 | 2890 |
| 2894 if (ShouldSaveDetailsLocally()) { | 2891 if (ShouldSaveDetailsLocally()) { |
| 2895 std::string guid = GetManager()->SaveImportedProfile(profile); | 2892 std::string guid = GetManager()->SaveImportedProfile(profile); |
| 2896 newly_saved_data_model_guids_[section] = guid; | 2893 newly_saved_data_model_guids_[section] = guid; |
| 2897 } | 2894 } |
| 2898 | 2895 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2929 | 2926 |
| 2930 string16 AutofillDialogControllerImpl::GetValueFromSection( | 2927 string16 AutofillDialogControllerImpl::GetValueFromSection( |
| 2931 DialogSection section, | 2928 DialogSection section, |
| 2932 ServerFieldType type) { | 2929 ServerFieldType type) { |
| 2933 DCHECK(SectionIsActive(section)); | 2930 DCHECK(SectionIsActive(section)); |
| 2934 | 2931 |
| 2935 scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section); | 2932 scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section); |
| 2936 if (wrapper) | 2933 if (wrapper) |
| 2937 return wrapper->GetInfo(AutofillType(type)); | 2934 return wrapper->GetInfo(AutofillType(type)); |
| 2938 | 2935 |
| 2939 DetailOutputMap output; | 2936 FieldValueMap output; |
| 2940 view_->GetUserInput(section, &output); | 2937 view_->GetUserInput(section, &output); |
| 2941 return GetValueForType(output, type); | 2938 return output[type]; |
| 2942 } | 2939 } |
| 2943 | 2940 |
| 2944 SuggestionsMenuModel* AutofillDialogControllerImpl:: | 2941 SuggestionsMenuModel* AutofillDialogControllerImpl:: |
| 2945 SuggestionsMenuModelForSection(DialogSection section) { | 2942 SuggestionsMenuModelForSection(DialogSection section) { |
| 2946 switch (section) { | 2943 switch (section) { |
| 2947 case SECTION_CC: | 2944 case SECTION_CC: |
| 2948 return &suggested_cc_; | 2945 return &suggested_cc_; |
| 2949 case SECTION_BILLING: | 2946 case SECTION_BILLING: |
| 2950 return &suggested_billing_; | 2947 return &suggested_billing_; |
| 2951 case SECTION_SHIPPING: | 2948 case SECTION_SHIPPING: |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3035 return false; | 3032 return false; |
| 3036 } | 3033 } |
| 3037 return true; | 3034 return true; |
| 3038 } | 3035 } |
| 3039 | 3036 |
| 3040 bool AutofillDialogControllerImpl::SectionIsValid( | 3037 bool AutofillDialogControllerImpl::SectionIsValid( |
| 3041 DialogSection section) { | 3038 DialogSection section) { |
| 3042 if (!IsManuallyEditingSection(section)) | 3039 if (!IsManuallyEditingSection(section)) |
| 3043 return true; | 3040 return true; |
| 3044 | 3041 |
| 3045 DetailOutputMap detail_outputs; | 3042 FieldValueMap detail_outputs; |
| 3046 view_->GetUserInput(section, &detail_outputs); | 3043 view_->GetUserInput(section, &detail_outputs); |
| 3047 return !InputsAreValid(section, detail_outputs).HasSureErrors(); | 3044 return !InputsAreValid(section, detail_outputs).HasSureErrors(); |
| 3048 } | 3045 } |
| 3049 | 3046 |
| 3050 bool AutofillDialogControllerImpl::IsCreditCardExpirationValid( | 3047 bool AutofillDialogControllerImpl::IsCreditCardExpirationValid( |
| 3051 const base::string16& year, | 3048 const base::string16& year, |
| 3052 const base::string16& month) const { | 3049 const base::string16& month) const { |
| 3053 // If the expiration is in the past as per the local clock, it's invalid. | 3050 // If the expiration is in the past as per the local clock, it's invalid. |
| 3054 base::Time now = base::Time::Now(); | 3051 base::Time now = base::Time::Now(); |
| 3055 if (!autofill::IsValidCreditCardExpirationDate(year, month, now)) | 3052 if (!autofill::IsValidCreditCardExpirationDate(year, month, now)) |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3190 | 3187 |
| 3191 GetWalletClient()->SaveToWallet(inputted_instrument.Pass(), | 3188 GetWalletClient()->SaveToWallet(inputted_instrument.Pass(), |
| 3192 inputted_address.Pass()); | 3189 inputted_address.Pass()); |
| 3193 } | 3190 } |
| 3194 | 3191 |
| 3195 scoped_ptr<wallet::Instrument> AutofillDialogControllerImpl:: | 3192 scoped_ptr<wallet::Instrument> AutofillDialogControllerImpl:: |
| 3196 CreateTransientInstrument() { | 3193 CreateTransientInstrument() { |
| 3197 if (!active_instrument_id_.empty()) | 3194 if (!active_instrument_id_.empty()) |
| 3198 return scoped_ptr<wallet::Instrument>(); | 3195 return scoped_ptr<wallet::Instrument>(); |
| 3199 | 3196 |
| 3200 DetailOutputMap output; | 3197 FieldValueMap output; |
| 3201 view_->GetUserInput(SECTION_CC_BILLING, &output); | 3198 view_->GetUserInput(SECTION_CC_BILLING, &output); |
| 3202 | 3199 |
| 3203 CreditCard card; | 3200 CreditCard card; |
| 3204 AutofillProfile profile; | 3201 AutofillProfile profile; |
| 3205 string16 cvc; | 3202 string16 cvc; |
| 3206 GetBillingInfoFromOutputs(output, &card, &cvc, &profile); | 3203 GetBillingInfoFromOutputs(output, &card, &cvc, &profile); |
| 3207 | 3204 |
| 3208 return scoped_ptr<wallet::Instrument>( | 3205 return scoped_ptr<wallet::Instrument>( |
| 3209 new wallet::Instrument(card, cvc, profile)); | 3206 new wallet::Instrument(card, cvc, profile)); |
| 3210 } | 3207 } |
| 3211 | 3208 |
| 3212 scoped_ptr<wallet::Address>AutofillDialogControllerImpl:: | 3209 scoped_ptr<wallet::Address>AutofillDialogControllerImpl:: |
| 3213 CreateTransientAddress() { | 3210 CreateTransientAddress() { |
| 3214 // If not using billing for shipping, just scrape the view. | 3211 // If not using billing for shipping, just scrape the view. |
| 3215 DetailOutputMap output; | 3212 FieldValueMap output; |
| 3216 view_->GetUserInput(SECTION_SHIPPING, &output); | 3213 view_->GetUserInput(SECTION_SHIPPING, &output); |
| 3217 | 3214 |
| 3218 AutofillProfile profile; | 3215 AutofillProfile profile; |
| 3219 FillFormGroupFromOutputs(output, &profile); | 3216 FillFormGroupFromOutputs(output, &profile); |
| 3220 | 3217 |
| 3221 return scoped_ptr<wallet::Address>(new wallet::Address(profile)); | 3218 return scoped_ptr<wallet::Address>(new wallet::Address(profile)); |
| 3222 } | 3219 } |
| 3223 | 3220 |
| 3224 void AutofillDialogControllerImpl::GetFullWallet() { | 3221 void AutofillDialogControllerImpl::GetFullWallet() { |
| 3225 DCHECK(is_submitting_); | 3222 DCHECK(is_submitting_); |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3483 } | 3480 } |
| 3484 | 3481 |
| 3485 void AutofillDialogControllerImpl::MaybeShowCreditCardBubble() { | 3482 void AutofillDialogControllerImpl::MaybeShowCreditCardBubble() { |
| 3486 if (!data_was_passed_back_) | 3483 if (!data_was_passed_back_) |
| 3487 return; | 3484 return; |
| 3488 | 3485 |
| 3489 if (newly_saved_card_) { | 3486 if (newly_saved_card_) { |
| 3490 scoped_ptr<AutofillProfile> billing_profile; | 3487 scoped_ptr<AutofillProfile> billing_profile; |
| 3491 if (IsManuallyEditingSection(SECTION_BILLING)) { | 3488 if (IsManuallyEditingSection(SECTION_BILLING)) { |
| 3492 // Scrape the view as the user's entering or updating information. | 3489 // Scrape the view as the user's entering or updating information. |
| 3493 DetailOutputMap outputs; | 3490 FieldValueMap outputs; |
| 3494 view_->GetUserInput(SECTION_BILLING, &outputs); | 3491 view_->GetUserInput(SECTION_BILLING, &outputs); |
| 3495 billing_profile.reset(new AutofillProfile); | 3492 billing_profile.reset(new AutofillProfile); |
| 3496 FillFormGroupFromOutputs(outputs, billing_profile.get()); | 3493 FillFormGroupFromOutputs(outputs, billing_profile.get()); |
| 3497 } else { | 3494 } else { |
| 3498 // Just snag the currently suggested profile. | 3495 // Just snag the currently suggested profile. |
| 3499 std::string item_key = SuggestionsMenuModelForSection(SECTION_BILLING)-> | 3496 std::string item_key = SuggestionsMenuModelForSection(SECTION_BILLING)-> |
| 3500 GetItemKeyForCheckedItem(); | 3497 GetItemKeyForCheckedItem(); |
| 3501 AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key); | 3498 AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key); |
| 3502 billing_profile.reset(new AutofillProfile(*profile)); | 3499 billing_profile.reset(new AutofillProfile(*profile)); |
| 3503 } | 3500 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3525 view_->UpdateButtonStrip(); | 3522 view_->UpdateButtonStrip(); |
| 3526 } | 3523 } |
| 3527 | 3524 |
| 3528 void AutofillDialogControllerImpl::FetchWalletCookie() { | 3525 void AutofillDialogControllerImpl::FetchWalletCookie() { |
| 3529 net::URLRequestContextGetter* request_context = profile_->GetRequestContext(); | 3526 net::URLRequestContextGetter* request_context = profile_->GetRequestContext(); |
| 3530 signin_helper_.reset(new wallet::WalletSigninHelper(this, request_context)); | 3527 signin_helper_.reset(new wallet::WalletSigninHelper(this, request_context)); |
| 3531 signin_helper_->StartWalletCookieValueFetch(); | 3528 signin_helper_->StartWalletCookieValueFetch(); |
| 3532 } | 3529 } |
| 3533 | 3530 |
| 3534 } // namespace autofill | 3531 } // namespace autofill |
| OLD | NEW |