OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 // |
| 5 // A stub implementation of internationalized address input fields for |
| 6 // interactive autofill dialog. The implementation always returns the same |
| 7 // address fields until libaddressinput library is integrated. |
| 8 // |
| 9 // Also, GetI18nFields() will call libaddressinput library to determine the |
| 10 // address fields instead of always returning US address fields. |
| 11 // |
| 12 // GuessCountry() uses only the application locale and should be improved to use |
| 13 // the timezone and possibly geolocation. |
| 14 |
| 15 #include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h" |
| 16 |
| 17 #include "base/command_line.h" |
| 18 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/common/chrome_switches.h" |
| 20 #include "components/autofill/core/browser/autofill_country.h" |
| 21 #include "grit/component_strings.h" |
| 22 #include "grit/generated_resources.h" |
| 23 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fi
eld.h" |
| 24 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui
_component.h" |
| 25 |
| 26 namespace autofill { |
| 27 namespace i18ninput { |
| 28 |
| 29 namespace { |
| 30 |
| 31 using i18n::addressinput::AddressField; |
| 32 using i18n::addressinput::AddressUiComponent; |
| 33 |
| 34 // Indexes into arrays of address field data. |
| 35 enum AddressFieldIndex { |
| 36 COUNTRY_INDEX, |
| 37 ADMIN_AREA_INDEX, |
| 38 LOCALITY_INDEX, |
| 39 POSTAL_CODE_INDEX, |
| 40 STREET_ADDRESS_1_INDEX, |
| 41 STREET_ADDRESS_2_INDEX, |
| 42 RECIPIENT_INDEX, |
| 43 }; |
| 44 |
| 45 // Indexes into arrays of street address line data. |
| 46 enum StreetAddressLine { |
| 47 STREET_ADDRESS_LINE_1, |
| 48 STREET_ADDRESS_LINE_2, |
| 49 }; |
| 50 |
| 51 // The number of address types. |
| 52 const int kNumberOfAddressTypes = ADDRESS_TYPE_BILLING + 1; |
| 53 |
| 54 // The maximum number of input fields. |
| 55 const int kMaxNumberOfInputFields = RECIPIENT_INDEX + 1; |
| 56 |
| 57 // The maximum number of street address lines. |
| 58 const int kMaxNumberOfStreetAddressLines = STREET_ADDRESS_LINE_2 + 1; |
| 59 |
| 60 // A mapping of StreetAddressLine to corresponding values in AddressFieldIndex. |
| 61 // Used to lookup address field data for street address lines. |
| 62 const AddressFieldIndex kStreetAddressLineIndex |
| 63 [kMaxNumberOfStreetAddressLines] = { |
| 64 STREET_ADDRESS_1_INDEX, |
| 65 STREET_ADDRESS_2_INDEX, |
| 66 }; |
| 67 |
| 68 // A mapping of AddressFieldIndex and AddressType to autofill field types. |
| 69 const ServerFieldType kServerFields[kMaxNumberOfInputFields] |
| 70 [kNumberOfAddressTypes] = { |
| 71 {ADDRESS_HOME_COUNTRY, ADDRESS_BILLING_COUNTRY}, |
| 72 {ADDRESS_HOME_STATE, ADDRESS_BILLING_STATE}, |
| 73 {ADDRESS_HOME_CITY, ADDRESS_BILLING_CITY}, |
| 74 {ADDRESS_HOME_ZIP, ADDRESS_BILLING_ZIP}, |
| 75 {ADDRESS_HOME_LINE1, ADDRESS_BILLING_LINE1}, |
| 76 {ADDRESS_HOME_LINE2, ADDRESS_BILLING_LINE2}, |
| 77 {NAME_FULL, NAME_BILLING_FULL}, |
| 78 }; |
| 79 |
| 80 // A mapping of AddressFieldIndex and AddressType to string identifiers for |
| 81 // placeholder text. |
| 82 const int kPlaceHolderStringIds[kMaxNumberOfInputFields] |
| 83 [kNumberOfAddressTypes] = { |
| 84 {IDS_AUTOFILL_FIELD_LABEL_COUNTRY, IDS_AUTOFILL_FIELD_LABEL_COUNTRY}, |
| 85 {IDS_AUTOFILL_FIELD_LABEL_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE}, |
| 86 {IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY, |
| 87 IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY}, |
| 88 {IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE, |
| 89 IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE}, |
| 90 {IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1, |
| 91 IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1}, |
| 92 {IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2, |
| 93 IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2}, |
| 94 {IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME, |
| 95 IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME}, |
| 96 }; |
| 97 |
| 98 // Returns the AddressFieldIndex for the given i18n::addressinput::AddressField. |
| 99 // If the address field is STREET_ADDRESS, then uses the given StreetAddressLine |
| 100 // to determine whether to return STREET_ADDRESS_1_INDEX or |
| 101 // STREET_ADDRESS_2_INDEX. |
| 102 AddressFieldIndex AddressFieldToIndex( |
| 103 i18n::addressinput::AddressField field_type, |
| 104 StreetAddressLine street_address_line) { |
| 105 switch (field_type) { |
| 106 case i18n::addressinput::COUNTRY: |
| 107 return COUNTRY_INDEX; |
| 108 case i18n::addressinput::ADMIN_AREA: |
| 109 return ADMIN_AREA_INDEX; |
| 110 case i18n::addressinput::LOCALITY: |
| 111 return LOCALITY_INDEX; |
| 112 case i18n::addressinput::POSTAL_CODE: |
| 113 return POSTAL_CODE_INDEX; |
| 114 case i18n::addressinput::STREET_ADDRESS: |
| 115 return kStreetAddressLineIndex[street_address_line]; |
| 116 return POSTAL_CODE_INDEX; |
| 117 case i18n::addressinput::RECIPIENT: |
| 118 return RECIPIENT_INDEX; |
| 119 default: |
| 120 NOTREACHED(); |
| 121 return COUNTRY_INDEX; |
| 122 } |
| 123 } |
| 124 |
| 125 // Sets the address field types and length hints for the given |country_region| |
| 126 // and |language|. |
| 127 void GetI18nFields(const std::string country_region, |
| 128 const std::string& language, |
| 129 std::vector<AddressField>* field_types, |
| 130 std::vector<AddressUiComponent::LengthHint>* length_hints) { |
| 131 // TODO(rouslan): Use the country_region and language specific |
| 132 // address input field types and names after libaddressinput is integrated. |
| 133 field_types->push_back(i18n::addressinput::RECIPIENT); |
| 134 length_hints->push_back(AddressUiComponent::HINT_LONG); |
| 135 |
| 136 field_types->push_back(i18n::addressinput::STREET_ADDRESS); |
| 137 length_hints->push_back(AddressUiComponent::HINT_LONG); |
| 138 |
| 139 field_types->push_back(i18n::addressinput::LOCALITY); |
| 140 length_hints->push_back(AddressUiComponent::HINT_LONG); |
| 141 |
| 142 field_types->push_back(i18n::addressinput::ADMIN_AREA); |
| 143 length_hints->push_back(AddressUiComponent::HINT_SHORT); |
| 144 |
| 145 field_types->push_back(i18n::addressinput::POSTAL_CODE); |
| 146 length_hints->push_back(AddressUiComponent::HINT_SHORT); |
| 147 |
| 148 field_types->push_back(i18n::addressinput::COUNTRY); |
| 149 length_hints->push_back(AddressUiComponent::HINT_LONG); |
| 150 } |
| 151 |
| 152 // Returns an incremented |row_index| if |length_hint| and |prev_length_hint| |
| 153 // indicate that the current input should start on a new line. |
| 154 int IncrementRowIndexBasedOnLengthHint( |
| 155 AddressUiComponent::LengthHint prev_length_hint, |
| 156 AddressUiComponent::LengthHint length_hint, |
| 157 int row_index) { |
| 158 if (length_hint == AddressUiComponent::HINT_LONG || |
| 159 prev_length_hint != length_hint) { |
| 160 return row_index + 1; |
| 161 } |
| 162 return row_index; |
| 163 } |
| 164 |
| 165 // Appends the |field_type| input to |inputs|. Appends |
| 166 // kMaxNumberOfStreetAddressLines inputs if |field_type| is STREET_ADDRESS. |
| 167 int BuildI18nInput(int row_index, |
| 168 i18n::addressinput::AddressField field_type, |
| 169 AddressUiComponent::LengthHint prev_length_hint, |
| 170 AddressUiComponent::LengthHint length_hint, |
| 171 AddressType address_type, |
| 172 DetailInputs* inputs) { |
| 173 int field_index = AddressFieldToIndex(field_type, STREET_ADDRESS_LINE_1); |
| 174 row_index = IncrementRowIndexBasedOnLengthHint( |
| 175 prev_length_hint, length_hint, row_index); |
| 176 DetailInput input = {row_index, kServerFields[field_index][address_type], |
| 177 kPlaceHolderStringIds[field_index][address_type]}; |
| 178 inputs->push_back(input); |
| 179 |
| 180 if (field_type == i18n::addressinput::STREET_ADDRESS) { |
| 181 field_index = AddressFieldToIndex(field_type, STREET_ADDRESS_LINE_2); |
| 182 row_index = IncrementRowIndexBasedOnLengthHint( |
| 183 prev_length_hint, length_hint, row_index); |
| 184 DetailInput input = {row_index, kServerFields[field_index][address_type], |
| 185 kPlaceHolderStringIds[field_index][address_type]}; |
| 186 inputs->push_back(input); |
| 187 } |
| 188 |
| 189 return row_index; |
| 190 } |
| 191 |
| 192 // Returns the language of the current application locale. |
| 193 std::string GetLocaleLanguage() { |
| 194 return AutofillCountry::CountryCodeForLocale( |
| 195 g_browser_process->GetApplicationLocale()); |
| 196 } |
| 197 |
| 198 } // namespace |
| 199 |
| 200 bool IsI18nAddressInputEnabled() { |
| 201 return CommandLine::ForCurrentProcess()->HasSwitch( |
| 202 ::switches::kEnableAutofillAddressInternationalization); |
| 203 } |
| 204 |
| 205 std::string GuessCountry() { |
| 206 if (!IsI18nAddressInputEnabled()) |
| 207 return "US"; |
| 208 |
| 209 // TODO(rouslan): Improve on this rudimentary implementation of guessing the |
| 210 // current country code. |
| 211 return GetLocaleLanguage(); |
| 212 } |
| 213 |
| 214 void BuildI18nInputs(AddressType address_type, |
| 215 const std::string& country_region, |
| 216 int row_index, |
| 217 DetailInputs* inputs) { |
| 218 std::vector<i18n::addressinput::AddressField> field_types; |
| 219 std::vector<AddressUiComponent::LengthHint> length_hints; |
| 220 GetI18nFields( |
| 221 country_region, GetLocaleLanguage(), &field_types, &length_hints); |
| 222 AddressUiComponent::LengthHint prev_length_hint = |
| 223 AddressUiComponent::HINT_LONG; |
| 224 for (size_t i = 0; i < field_types.size() && i < length_hints.size(); ++i) { |
| 225 row_index = BuildI18nInput(row_index, |
| 226 field_types[i], |
| 227 prev_length_hint, |
| 228 length_hints[i], |
| 229 address_type, |
| 230 inputs); |
| 231 prev_length_hint = length_hints[i]; |
| 232 } |
| 233 } |
| 234 |
| 235 } // namespace i18ninput |
| 236 } // namespace autofill |
OLD | NEW |