autofill_dialog_i18n_input.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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 // TODO(rouslan): Store the language code for the autofill profile. 43 // http://crbug.com/354955 44 std::vector<AddressUiComponent> components( 45 ::i18n::addressinput::BuildComponents( 46 country_code, g_browser_process->GetApplicationLocale(), NULL)); 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#if defined(OS_MACOSX) || defined(OS_ANDROID) 64 if (component.field == ::i18n::addressinput::STREET_ADDRESS && 65 component.length_hint == AddressUiComponent::HINT_LONG) { 66 // TODO(dbeam): support more than 2 address lines. http://crbug.com/324889 67 ServerFieldType server_type = 68 billing ? ADDRESS_BILLING_LINE2 : ADDRESS_HOME_LINE2; 69 base::string16 placeholder = l10n_util::GetStringUTF16(component.name_id); 70 DetailInput input = { length, server_type, placeholder }; 71 inputs->push_back(input); 72 } 73#endif 74 } 75 76 ServerFieldType server_type = 77 billing ? ADDRESS_BILLING_COUNTRY : ADDRESS_HOME_COUNTRY; 78 base::string16 placeholder_text = 79 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COUNTRY); 80 DetailInput input = { DetailInput::LONG, server_type, placeholder_text }; 81 inputs->push_back(input); 82} 83 84bool CardHasCompleteAndVerifiedData(const CreditCard& card) { 85 if (!card.IsVerified()) 86 return false; 87 88 const ServerFieldType required_fields[] = { 89 CREDIT_CARD_NUMBER, 90 CREDIT_CARD_EXP_MONTH, 91 CREDIT_CARD_EXP_4_DIGIT_YEAR, 92 }; 93 94 for (size_t i = 0; i < arraysize(required_fields); ++i) { 95 if (card.GetRawInfo(required_fields[i]).empty()) 96 return false; 97 } 98 99 return true; 100} 101 102bool AddressHasCompleteAndVerifiedData(const AutofillProfile& profile) { 103 if (!profile.IsVerified()) 104 return false; 105 106 base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY); 107 if (country_code.empty()) 108 return false; 109 110 std::vector<AddressField> required_fields = 111 ::i18n::addressinput::GetRequiredFields(base::UTF16ToUTF8(country_code)); 112 113 for (size_t i = 0; i < required_fields.size(); ++i) { 114 ServerFieldType type = 115 TypeForField(required_fields[i], common::ADDRESS_TYPE_SHIPPING); 116 if (profile.GetRawInfo(type).empty()) 117 return false; 118 } 119 120 const ServerFieldType more_required_fields[] = { 121 NAME_FULL, 122 PHONE_HOME_WHOLE_NUMBER 123 }; 124 125 for (size_t i = 0; i < arraysize(more_required_fields); ++i) { 126 if (profile.GetRawInfo(more_required_fields[i]).empty()) 127 return false; 128 } 129 130 return true; 131} 132 133ServerFieldType TypeForField(AddressField address_field, 134 common::AddressType address_type) { 135 bool billing = address_type == common::ADDRESS_TYPE_BILLING; 136 switch (address_field) { 137 case ::i18n::addressinput::COUNTRY: 138 return billing ? ADDRESS_BILLING_COUNTRY : ADDRESS_HOME_COUNTRY; 139 case ::i18n::addressinput::ADMIN_AREA: 140 return billing ? ADDRESS_BILLING_STATE : ADDRESS_HOME_STATE; 141 case ::i18n::addressinput::LOCALITY: 142 return billing ? ADDRESS_BILLING_CITY : ADDRESS_HOME_CITY; 143 case ::i18n::addressinput::DEPENDENT_LOCALITY: 144 return billing ? ADDRESS_BILLING_DEPENDENT_LOCALITY : 145 ADDRESS_HOME_DEPENDENT_LOCALITY; 146 case ::i18n::addressinput::POSTAL_CODE: 147 return billing ? ADDRESS_BILLING_ZIP : ADDRESS_HOME_ZIP; 148 case ::i18n::addressinput::SORTING_CODE: 149 return billing ? ADDRESS_BILLING_SORTING_CODE : ADDRESS_HOME_SORTING_CODE; 150#if defined(OS_MACOSX) || defined(OS_ANDROID) 151 case ::i18n::addressinput::STREET_ADDRESS: 152 return billing ? ADDRESS_BILLING_LINE1 : ADDRESS_HOME_LINE1; 153#else 154 case ::i18n::addressinput::STREET_ADDRESS: 155 return billing ? ADDRESS_BILLING_STREET_ADDRESS : 156 ADDRESS_HOME_STREET_ADDRESS; 157#endif 158 case ::i18n::addressinput::RECIPIENT: 159 return billing ? NAME_BILLING_FULL : NAME_FULL; 160 case ::i18n::addressinput::ORGANIZATION: 161 return COMPANY_NAME; 162 } 163 NOTREACHED(); 164 return UNKNOWN_TYPE; 165} 166 167bool FieldForType(ServerFieldType server_type, 168 ::i18n::addressinput::AddressField* field) { 169 switch (server_type) { 170 case ADDRESS_BILLING_COUNTRY: 171 case ADDRESS_HOME_COUNTRY: 172 if (field) 173 *field = ::i18n::addressinput::COUNTRY; 174 return true; 175 case ADDRESS_BILLING_STATE: 176 case ADDRESS_HOME_STATE: 177 if (field) 178 *field = ::i18n::addressinput::ADMIN_AREA; 179 return true; 180 case ADDRESS_BILLING_CITY: 181 case ADDRESS_HOME_CITY: 182 if (field) 183 *field = ::i18n::addressinput::LOCALITY; 184 return true; 185 case ADDRESS_BILLING_DEPENDENT_LOCALITY: 186 case ADDRESS_HOME_DEPENDENT_LOCALITY: 187 if (field) 188 *field = ::i18n::addressinput::DEPENDENT_LOCALITY; 189 return true; 190 case ADDRESS_BILLING_SORTING_CODE: 191 case ADDRESS_HOME_SORTING_CODE: 192 if (field) 193 *field = ::i18n::addressinput::SORTING_CODE; 194 return true; 195 case ADDRESS_BILLING_ZIP: 196 case ADDRESS_HOME_ZIP: 197 if (field) 198 *field = ::i18n::addressinput::POSTAL_CODE; 199 return true; 200 case ADDRESS_BILLING_STREET_ADDRESS: 201 case ADDRESS_BILLING_LINE1: 202 case ADDRESS_BILLING_LINE2: 203 case ADDRESS_HOME_STREET_ADDRESS: 204 case ADDRESS_HOME_LINE1: 205 case ADDRESS_HOME_LINE2: 206 if (field) 207 *field = ::i18n::addressinput::STREET_ADDRESS; 208 return true; 209 case COMPANY_NAME: 210 if (field) 211 *field = ::i18n::addressinput::ORGANIZATION; 212 return true; 213 case NAME_BILLING_FULL: 214 case NAME_FULL: 215 if (field) 216 *field = ::i18n::addressinput::RECIPIENT; 217 return true; 218 default: 219 return false; 220 } 221} 222 223void CreateAddressData( 224 const base::Callback<base::string16(const AutofillType&)>& get_info, 225 AddressData* address_data) { 226 address_data->recipient = UTF16ToUTF8(get_info.Run(AutofillType(NAME_FULL))); 227 address_data->country_code = UTF16ToUTF8( 228 get_info.Run(AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_SHIPPING))); 229 DCHECK_EQ(2U, address_data->country_code.size()); 230 address_data->administrative_area = UTF16ToUTF8( 231 get_info.Run(AutofillType(ADDRESS_HOME_STATE))); 232 address_data->locality = UTF16ToUTF8( 233 get_info.Run(AutofillType(ADDRESS_HOME_CITY))); 234 address_data->dependent_locality = UTF16ToUTF8( 235 get_info.Run(AutofillType(ADDRESS_HOME_DEPENDENT_LOCALITY))); 236 address_data->sorting_code = UTF16ToUTF8( 237 get_info.Run(AutofillType(ADDRESS_HOME_SORTING_CODE))); 238 address_data->postal_code = UTF16ToUTF8( 239 get_info.Run(AutofillType(ADDRESS_HOME_ZIP))); 240 base::SplitString( 241 UTF16ToUTF8(get_info.Run(AutofillType(ADDRESS_HOME_STREET_ADDRESS))), 242 '\n', 243 &address_data->address_lines); 244} 245 246bool CountryIsFullySupported(const std::string& country_code) { 247 DCHECK_EQ(2U, country_code.size()); 248 std::vector< ::i18n::addressinput::AddressUiComponent> components = 249 ::i18n::addressinput::BuildComponents( 250 country_code, g_browser_process->GetApplicationLocale(), NULL); 251 for (size_t i = 0; i < components.size(); ++i) { 252 if (components[i].field == ::i18n::addressinput::DEPENDENT_LOCALITY) 253 return false; 254 } 255 return true; 256} 257 258} // namespace i18ninput 259} // namespace autofill 260