Index: chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc |
diff --git a/chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc b/chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..94e3f0bedddd872172bb3ff9c63f2f0de1c11b41 |
--- /dev/null |
+++ b/chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc |
@@ -0,0 +1,263 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+// |
+// A stub implementation of internationalized address input fields for |
+// interactive autofill dialog. The implementation always returns the same |
+// address fields until libaddressinput library is integrated. |
+// |
+// After libaddressinput library is integrated, these enums will removed below: |
+// i18n::addressinput::AddressField |
+// i18n::addressinput::LengthHint |
+// Also, GetI18nFields() will call libaddressinput library to determine the |
+// address fields instead of always returning US address fields. |
+// |
+// GuessCountry() uses only the application locale and should be improved to use |
+// the timezone and possibly geolocation. |
+ |
+#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h" |
+ |
+#include "base/command_line.h" |
+#include "chrome/browser/browser_process.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "components/autofill/core/browser/autofill_country.h" |
+#include "grit/component_strings.h" |
+#include "grit/generated_resources.h" |
+ |
+namespace autofill { |
+namespace i18ninput { |
+ |
+namespace { |
+ |
+// TODO(rouslan): Use the enums from libaddressinput instead after the library |
+// has been integrated. |
+namespace i18n { |
+namespace addressinput { |
+ |
+enum AddressField { |
+ COUNTRY, |
+ ADMIN_AREA, |
+ LOCALITY, |
+ DEPENDENT_LOCALITY, |
+ POSTAL_CODE, |
+ SORTING_CODE, |
+ STREET_ADDRESS, |
+ ORGANIZATION, |
+ RECIPIENT, |
+}; |
+ |
+enum LengthHint { |
+ LENGTH_HINT_SHORT, |
+ LENGTH_HINT_LONG, |
+}; |
+ |
+} // namespace addressinput |
+} // namespace i18n |
+ |
+// Indexes into arrays of address field data. The values in |
+// i18n::addressinput::AddressField enum cannot be used directly because they |
+// are not sequential. |
+enum AddressFieldIndex { |
+ COUNTRY_INDEX, |
+ ADMIN_AREA_INDEX, |
+ LOCALITY_INDEX, |
+ POSTAL_CODE_INDEX, |
+ STREET_ADDRESS_1_INDEX, |
+ STREET_ADDRESS_2_INDEX, |
+ RECIPIENT_INDEX, |
+}; |
+ |
+// Indexes into arrays of street address line data. |
+enum StreetAddressLine { |
+ STREET_ADDRESS_LINE_1, |
+ STREET_ADDRESS_LINE_2, |
+}; |
+ |
+// The number of address types. |
+const int kNumberOfAddressTypes = ADDRESS_TYPE_BILLING + 1; |
+ |
+// The maximum number of input fields. |
+const int kMaxNumberOfInputFields = RECIPIENT_INDEX + 1; |
+ |
+// The maximum number of street address lines. |
+const int kMaxNumberOfStreetAddressLines = STREET_ADDRESS_LINE_2 + 1; |
+ |
+// A mapping of StreetAddressLine to corresponding values in AddressFieldIndex. |
+// Used to lookup address field data for street address lines. |
+const AddressFieldIndex kStreetAddressLineIndex |
+ [kMaxNumberOfStreetAddressLines] = { |
+ STREET_ADDRESS_1_INDEX, |
+ STREET_ADDRESS_2_INDEX, |
+}; |
+ |
+// A mapping of AddressFieldIndex and AddressType to autofill field types. |
+const ServerFieldType kServerFields[kMaxNumberOfInputFields] |
+ [kNumberOfAddressTypes] = { |
+ {ADDRESS_HOME_COUNTRY, ADDRESS_BILLING_COUNTRY}, |
+ {ADDRESS_HOME_STATE, ADDRESS_BILLING_STATE}, |
+ {ADDRESS_HOME_CITY, ADDRESS_BILLING_CITY}, |
+ {ADDRESS_HOME_ZIP, ADDRESS_BILLING_ZIP}, |
+ {ADDRESS_HOME_LINE1, ADDRESS_BILLING_LINE1}, |
+ {ADDRESS_HOME_LINE2, ADDRESS_BILLING_LINE2}, |
+ {NAME_FULL, NAME_BILLING_FULL}, |
+}; |
+ |
+// A mapping of AddressFieldIndex and AddressType to string identifiers for |
+// placeholder text. |
+const int kPlaceHolderStringIds[kMaxNumberOfInputFields] |
+ [kNumberOfAddressTypes] = { |
+ {IDS_AUTOFILL_FIELD_LABEL_COUNTRY, IDS_AUTOFILL_FIELD_LABEL_COUNTRY}, |
+ {IDS_AUTOFILL_FIELD_LABEL_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE}, |
+ {IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY, |
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY}, |
+ {IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE, |
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE}, |
+ {IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1, |
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1}, |
+ {IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2, |
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2}, |
+ {IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME, |
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME}, |
+}; |
+ |
+// Returns the AddressFieldIndex for the given i18n::addressinput::AddressField. |
+// If the address field is STREET_ADDRESS, then uses the given StreetAddressLine |
+// to determine whether to return STREET_ADDRESS_1_INDEX or |
+// STREET_ADDRESS_2_INDEX. |
+AddressFieldIndex AddressFieldToIndex( |
+ i18n::addressinput::AddressField field_type, |
+ StreetAddressLine street_address_line) { |
+ switch (field_type) { |
+ case i18n::addressinput::COUNTRY: |
+ return COUNTRY_INDEX; |
+ case i18n::addressinput::ADMIN_AREA: |
+ return ADMIN_AREA_INDEX; |
+ case i18n::addressinput::LOCALITY: |
+ return LOCALITY_INDEX; |
+ case i18n::addressinput::POSTAL_CODE: |
+ return POSTAL_CODE_INDEX; |
+ case i18n::addressinput::STREET_ADDRESS: |
+ return kStreetAddressLineIndex[street_address_line]; |
+ return POSTAL_CODE_INDEX; |
+ case i18n::addressinput::RECIPIENT: |
+ return RECIPIENT_INDEX; |
+ default: |
+ NOTREACHED(); |
+ return COUNTRY_INDEX; |
+ } |
+} |
+ |
+// Sets the address field types and length hints for the given |country_region| |
+// and |language|. |
+void GetI18nFields(const std::string country_region, |
+ const std::string& language, |
+ std::vector<i18n::addressinput::AddressField>* field_types, |
+ std::vector<i18n::addressinput::LengthHint>* length_hints) { |
+ // TODO(rouslan): Use the country_region and language specific |
+ // address input field types and names after libaddressinput is integrated. |
+ field_types->push_back(i18n::addressinput::RECIPIENT); |
+ length_hints->push_back(i18n::addressinput::LENGTH_HINT_LONG); |
+ |
+ field_types->push_back(i18n::addressinput::STREET_ADDRESS); |
+ length_hints->push_back(i18n::addressinput::LENGTH_HINT_LONG); |
+ |
+ field_types->push_back(i18n::addressinput::LOCALITY); |
+ length_hints->push_back(i18n::addressinput::LENGTH_HINT_LONG); |
+ |
+ field_types->push_back(i18n::addressinput::ADMIN_AREA); |
+ length_hints->push_back(i18n::addressinput::LENGTH_HINT_SHORT); |
+ |
+ field_types->push_back(i18n::addressinput::POSTAL_CODE); |
+ length_hints->push_back(i18n::addressinput::LENGTH_HINT_SHORT); |
+ |
+ field_types->push_back(i18n::addressinput::COUNTRY); |
+ length_hints->push_back(i18n::addressinput::LENGTH_HINT_LONG); |
+ |
+} |
+ |
+// Returns an incremented |row_index| if |length_hint| and |prev_length_hint| |
+// indicate that the current input should start on a new line. |
+int IncrementRowIndexBasedOnLengthHint( |
+ i18n::addressinput::LengthHint prev_length_hint, |
+ i18n::addressinput::LengthHint length_hint, |
+ int row_index) { |
+ if (length_hint == i18n::addressinput::LENGTH_HINT_LONG || |
+ prev_length_hint != length_hint) { |
+ return row_index + 1; |
+ } |
+ return row_index; |
+} |
+ |
+// Appends the |field_type| input to |inputs|. Appends |
+// kMaxNumberOfStreetAddressLines inputs if |field_type| is STREET_ADDRESS. |
+int BuildI18nInput(int row_index, |
+ i18n::addressinput::AddressField field_type, |
+ i18n::addressinput::LengthHint prev_length_hint, |
+ i18n::addressinput::LengthHint length_hint, |
+ AddressType address_type, |
+ DetailInputs* inputs) { |
+ int field_index = AddressFieldToIndex(field_type, STREET_ADDRESS_LINE_1); |
+ row_index = IncrementRowIndexBasedOnLengthHint( |
+ prev_length_hint, length_hint, row_index); |
+ DetailInput input = {row_index, kServerFields[field_index][address_type], |
+ kPlaceHolderStringIds[field_index][address_type]}; |
+ inputs->push_back(input); |
+ |
+ if (field_type == i18n::addressinput::STREET_ADDRESS) { |
+ field_index = AddressFieldToIndex(field_type, STREET_ADDRESS_LINE_2); |
+ row_index = IncrementRowIndexBasedOnLengthHint( |
+ prev_length_hint, length_hint, row_index); |
+ DetailInput input = {row_index, kServerFields[field_index][address_type], |
+ kPlaceHolderStringIds[field_index][address_type]}; |
+ inputs->push_back(input); |
+ } |
+ |
+ return row_index; |
+} |
+ |
+// Returns the language of the current application locale. |
+std::string GetLocaleLanguage() { |
+ const std::string& locale = g_browser_process->GetApplicationLocale(); |
+ return locale.substr(0, locale.find('-')); |
+} |
+ |
+} // namespace |
+ |
+bool IsI18nAddressInputEnabled() { |
+ return CommandLine::ForCurrentProcess()->HasSwitch( |
+ ::switches::kEnableAutofillAddressInternationalization); |
+} |
+ |
+std::string GuessCountry() { |
+ if (!IsI18nAddressInputEnabled()) |
+ return "US"; |
+ |
+ // TODO(rouslan): Improve on this rudimentary implementation of guessing the |
+ // current country code. |
+ return AutofillCountry::CountryCodeForLocale( |
+ g_browser_process->GetApplicationLocale()); |
+} |
+ |
+void BuildI18nInputs(AddressType address_type, |
+ const std::string& country_region, |
+ int row_index, |
+ DetailInputs* inputs) { |
+ std::vector<i18n::addressinput::AddressField> field_types; |
+ std::vector<i18n::addressinput::LengthHint> length_hints; |
+ GetI18nFields( |
+ country_region, GetLocaleLanguage(), &field_types, &length_hints); |
+ i18n::addressinput::LengthHint prev_length_hint = |
+ i18n::addressinput::LENGTH_HINT_LONG; |
+ for (size_t i = 0; i < field_types.size() && i < length_hints.size(); ++i) { |
+ row_index = BuildI18nInput(row_index, |
+ field_types[i], |
+ prev_length_hint, |
+ length_hints[i], |
+ address_type, |
+ inputs); |
+ prev_length_hint = length_hints[i]; |
+ } |
+} |
+ |
+} // namespace i18ninput |
+} // namespace autofill |