autofill_dialog_i18n_input.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h" 6 7#include "base/strings/string_split.h" 8#include "base/strings/utf_string_conversions.h" 9#include "chrome/browser/browser_process.h" 10#include "components/autofill/core/browser/autofill_profile.h" 11#include "components/autofill/core/browser/credit_card.h" 12#include "components/autofill/core/browser/field_types.h" 13#include "grit/component_strings.h" 14#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h" 15#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_field.h" 16#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h" 17#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui_component.h" 18#include "ui/base/l10n/l10n_util.h" 19 20namespace autofill { 21namespace i18ninput { 22 23namespace { 24 25using base::UTF16ToUTF8; 26using ::i18n::addressinput::AddressData; 27using ::i18n::addressinput::AddressField; 28using ::i18n::addressinput::AddressUiComponent; 29 30DetailInput::Length LengthFromHint(AddressUiComponent::LengthHint hint) { 31 if (hint == AddressUiComponent::HINT_SHORT) 32 return DetailInput::SHORT; 33 DCHECK_EQ(hint, AddressUiComponent::HINT_LONG); 34 return DetailInput::LONG; 35} 36 37} // namespace 38 39void BuildAddressInputs(common::AddressType address_type, 40 const std::string& country_code, 41 DetailInputs* inputs, 42 std::string* language_code) { 43 std::vector<AddressUiComponent> components( 44 ::i18n::addressinput::BuildComponents( 45 country_code, g_browser_process->GetApplicationLocale(), 46 language_code)); 47 48 const bool billing = address_type == common::ADDRESS_TYPE_BILLING; 49 50 for (size_t i = 0; i < components.size(); ++i) { 51 const AddressUiComponent& component = components[i]; 52 if (component.field == ::i18n::addressinput::ORGANIZATION) { 53 // TODO(dbeam): figure out when we actually need this. 54 continue; 55 } 56 57 ServerFieldType server_type = TypeForField(component.field, address_type); 58 DetailInput::Length length = LengthFromHint(component.length_hint); 59 base::string16 placeholder = l10n_util::GetStringUTF16(component.name_id); 60 DetailInput input = { length, server_type, placeholder }; 61 inputs->push_back(input); 62 } 63 64 ServerFieldType server_type = 65 billing ? ADDRESS_BILLING_COUNTRY : ADDRESS_HOME_COUNTRY; 66 base::string16 placeholder_text = 67 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COUNTRY); 68 DetailInput input = { DetailInput::LONG, server_type, placeholder_text }; 69 inputs->push_back(input); 70} 71 72bool CardHasCompleteAndVerifiedData(const CreditCard& card) { 73 if (!card.IsVerified()) 74 return false; 75 76 const ServerFieldType required_fields[] = { 77 CREDIT_CARD_NUMBER, 78 CREDIT_CARD_EXP_MONTH, 79 CREDIT_CARD_EXP_4_DIGIT_YEAR, 80 }; 81 82 for (size_t i = 0; i < arraysize(required_fields); ++i) { 83 if (card.GetRawInfo(required_fields[i]).empty()) 84 return false; 85 } 86 87 return true; 88} 89 90bool AddressHasCompleteAndVerifiedData(const AutofillProfile& profile) { 91 if (!profile.IsVerified()) 92 return false; 93 94 base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY); 95 if (country_code.empty()) 96 return false; 97 98 std::vector<AddressField> required_fields = 99 ::i18n::addressinput::GetRequiredFields(base::UTF16ToUTF8(country_code)); 100 101 for (size_t i = 0; i < required_fields.size(); ++i) { 102 ServerFieldType type = 103 TypeForField(required_fields[i], common::ADDRESS_TYPE_SHIPPING); 104 if (profile.GetRawInfo(type).empty()) 105 return false; 106 } 107 108 const ServerFieldType more_required_fields[] = { 109 NAME_FULL, 110 PHONE_HOME_WHOLE_NUMBER 111 }; 112 113 for (size_t i = 0; i < arraysize(more_required_fields); ++i) { 114 if (profile.GetRawInfo(more_required_fields[i]).empty()) 115 return false; 116 } 117 118 return true; 119} 120 121ServerFieldType TypeForField(AddressField address_field, 122 common::AddressType address_type) { 123 bool billing = address_type == common::ADDRESS_TYPE_BILLING; 124 switch (address_field) { 125 case ::i18n::addressinput::COUNTRY: 126 return billing ? ADDRESS_BILLING_COUNTRY : ADDRESS_HOME_COUNTRY; 127 case ::i18n::addressinput::ADMIN_AREA: 128 return billing ? ADDRESS_BILLING_STATE : ADDRESS_HOME_STATE; 129 case ::i18n::addressinput::LOCALITY: 130 return billing ? ADDRESS_BILLING_CITY : ADDRESS_HOME_CITY; 131 case ::i18n::addressinput::DEPENDENT_LOCALITY: 132 return billing ? ADDRESS_BILLING_DEPENDENT_LOCALITY : 133 ADDRESS_HOME_DEPENDENT_LOCALITY; 134 case ::i18n::addressinput::POSTAL_CODE: 135 return billing ? ADDRESS_BILLING_ZIP : ADDRESS_HOME_ZIP; 136 case ::i18n::addressinput::SORTING_CODE: 137 return billing ? ADDRESS_BILLING_SORTING_CODE : ADDRESS_HOME_SORTING_CODE; 138 case ::i18n::addressinput::STREET_ADDRESS: 139 return billing ? ADDRESS_BILLING_STREET_ADDRESS : 140 ADDRESS_HOME_STREET_ADDRESS; 141 case ::i18n::addressinput::RECIPIENT: 142 return billing ? NAME_BILLING_FULL : NAME_FULL; 143 case ::i18n::addressinput::ORGANIZATION: 144 return COMPANY_NAME; 145 } 146 NOTREACHED(); 147 return UNKNOWN_TYPE; 148} 149 150bool FieldForType(ServerFieldType server_type, 151 ::i18n::addressinput::AddressField* field) { 152 switch (server_type) { 153 case ADDRESS_BILLING_COUNTRY: 154 case ADDRESS_HOME_COUNTRY: 155 if (field) 156 *field = ::i18n::addressinput::COUNTRY; 157 return true; 158 case ADDRESS_BILLING_STATE: 159 case ADDRESS_HOME_STATE: 160 if (field) 161 *field = ::i18n::addressinput::ADMIN_AREA; 162 return true; 163 case ADDRESS_BILLING_CITY: 164 case ADDRESS_HOME_CITY: 165 if (field) 166 *field = ::i18n::addressinput::LOCALITY; 167 return true; 168 case ADDRESS_BILLING_DEPENDENT_LOCALITY: 169 case ADDRESS_HOME_DEPENDENT_LOCALITY: 170 if (field) 171 *field = ::i18n::addressinput::DEPENDENT_LOCALITY; 172 return true; 173 case ADDRESS_BILLING_SORTING_CODE: 174 case ADDRESS_HOME_SORTING_CODE: 175 if (field) 176 *field = ::i18n::addressinput::SORTING_CODE; 177 return true; 178 case ADDRESS_BILLING_ZIP: 179 case ADDRESS_HOME_ZIP: 180 if (field) 181 *field = ::i18n::addressinput::POSTAL_CODE; 182 return true; 183 case ADDRESS_BILLING_STREET_ADDRESS: 184 case ADDRESS_BILLING_LINE1: 185 case ADDRESS_BILLING_LINE2: 186 case ADDRESS_HOME_STREET_ADDRESS: 187 case ADDRESS_HOME_LINE1: 188 case ADDRESS_HOME_LINE2: 189 if (field) 190 *field = ::i18n::addressinput::STREET_ADDRESS; 191 return true; 192 case COMPANY_NAME: 193 if (field) 194 *field = ::i18n::addressinput::ORGANIZATION; 195 return true; 196 case NAME_BILLING_FULL: 197 case NAME_FULL: 198 if (field) 199 *field = ::i18n::addressinput::RECIPIENT; 200 return true; 201 default: 202 return false; 203 } 204} 205 206void CreateAddressData( 207 const base::Callback<base::string16(const AutofillType&)>& get_info, 208 AddressData* address_data) { 209 address_data->recipient = UTF16ToUTF8(get_info.Run(AutofillType(NAME_FULL))); 210 address_data->country_code = UTF16ToUTF8( 211 get_info.Run(AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_SHIPPING))); 212 DCHECK_EQ(2U, address_data->country_code.size()); 213 address_data->administrative_area = UTF16ToUTF8( 214 get_info.Run(AutofillType(ADDRESS_HOME_STATE))); 215 address_data->locality = UTF16ToUTF8( 216 get_info.Run(AutofillType(ADDRESS_HOME_CITY))); 217 address_data->dependent_locality = UTF16ToUTF8( 218 get_info.Run(AutofillType(ADDRESS_HOME_DEPENDENT_LOCALITY))); 219 address_data->sorting_code = UTF16ToUTF8( 220 get_info.Run(AutofillType(ADDRESS_HOME_SORTING_CODE))); 221 address_data->postal_code = UTF16ToUTF8( 222 get_info.Run(AutofillType(ADDRESS_HOME_ZIP))); 223 base::SplitString( 224 UTF16ToUTF8(get_info.Run(AutofillType(ADDRESS_HOME_STREET_ADDRESS))), 225 '\n', 226 &address_data->address_lines); 227} 228 229bool CountryIsFullySupported(const std::string& country_code) { 230 DCHECK_EQ(2U, country_code.size()); 231 std::vector< ::i18n::addressinput::AddressUiComponent> components = 232 ::i18n::addressinput::BuildComponents( 233 country_code, g_browser_process->GetApplicationLocale(), NULL); 234 for (size_t i = 0; i < components.size(); ++i) { 235 if (components[i].field == ::i18n::addressinput::DEPENDENT_LOCALITY) 236 return false; 237 } 238 return true; 239} 240 241} // namespace i18ninput 242} // namespace autofill 243