Commit c220d4c9 authored by dbeam@chromium.org's avatar dbeam@chromium.org

Ask libaddressinput for address components to use in requestAutocomplete().

This change will cause slightly different translations and address layout to
show when the --enable-autofill-address-i18n flag is passed.

Next up:
- pull translations from chrome rather than libaddressinput
- show country combobox and rebuild inputs on switch

Based on https://codereview.chromium.org/25620002 by Rouslan Solomakhin <rouslan@chromium.org>.

BUG=317837
TBR=aruslan

Review URL: https://codereview.chromium.org/63053003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243189 0039d316-1c4b-4281-b951-d872f2087c98
parent b831aa4f
......@@ -92,7 +92,7 @@ void FillOutputForSection(
wallet::FullWallet* full_wallet,
const base::string16& email_address) {
DetailInputs inputs;
common::BuildInputsForSection(section, &inputs);
common::BuildInputsForSection(section, "US", &inputs);
FillOutputForSectionWithComparator(
section, inputs,
......@@ -250,7 +250,7 @@ void AutofillDialogControllerAndroid::Show() {
bool request_shipping_address = false;
{
DetailInputs inputs;
common::BuildInputsForSection(SECTION_SHIPPING, &inputs);
common::BuildInputsForSection(SECTION_SHIPPING, "US", &inputs);
EmptyDataModelWrapper empty_wrapper;
request_shipping_address = empty_wrapper.FillFormStructure(
inputs,
......
include_rules = [
'+third_party/libaddressinput/src/cpp/include',
]
......@@ -13,6 +13,11 @@
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/webkit_resources.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(OS_ANDROID)
#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
#endif // !defined(OS_ANDROID)
namespace autofill {
namespace common {
......@@ -71,79 +76,107 @@ void BuildInputs(const DetailInput* input_template,
}
}
bool IsI18nInputEnabled() {
#if defined(OS_ANDROID)
return false;
#else
return i18ninput::Enabled();
#endif
}
void BuildI18nAddressInputs(AddressType address_type,
const std::string& country_code,
DetailInputs* inputs) {
#if defined(OS_ANDROID)
NOTREACHED();
#else
i18ninput::BuildAddressInputs(address_type, country_code, inputs);
#endif
}
// Constructs |inputs| from template data for a given |dialog_section|.
void BuildInputsForSection(DialogSection dialog_section,
const std::string& country_code,
DetailInputs* inputs) {
using l10n_util::GetStringUTF16;
const DetailInput kCCInputs[] = {
{ DetailInput::LONG,
CREDIT_CARD_NUMBER,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER) },
{ DetailInput::SHORT,
CREDIT_CARD_EXP_MONTH,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH) },
{ DetailInput::SHORT,
CREDIT_CARD_EXP_4_DIGIT_YEAR,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR },
{ DetailInput::SHORT,
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR) },
{ DetailInput::SHORT_EOL,
CREDIT_CARD_VERIFICATION_CODE,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC,
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC),
1.5 },
};
const DetailInput kBillingInputs[] = {
{ DetailInput::LONG,
NAME_BILLING_FULL,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME) },
{ DetailInput::LONG,
ADDRESS_BILLING_LINE1,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1) },
{ DetailInput::LONG,
ADDRESS_BILLING_LINE2,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2) },
{ DetailInput::LONG,
ADDRESS_BILLING_CITY,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
// TODO(estade): state placeholder should depend on locale.
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY) },
{ DetailInput::SHORT,
ADDRESS_BILLING_STATE,
IDS_AUTOFILL_FIELD_LABEL_STATE },
{ DetailInput::SHORT,
GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_STATE) },
{ DetailInput::SHORT_EOL,
ADDRESS_BILLING_ZIP,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE) },
// We don't allow the user to change the country: http://crbug.com/247518
{ DetailInput::NONE, ADDRESS_BILLING_COUNTRY, 0 },
{ DetailInput::NONE, ADDRESS_BILLING_COUNTRY },
};
const DetailInput kBillingPhoneInputs[] = {
{ DetailInput::LONG,
PHONE_BILLING_WHOLE_NUMBER,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER) },
};
const DetailInput kEmailInputs[] = {
{ DetailInput::LONG, EMAIL_ADDRESS, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
{ DetailInput::LONG,
EMAIL_ADDRESS,
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL) },
};
const DetailInput kShippingInputs[] = {
{ DetailInput::LONG,
NAME_FULL,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME) },
{ DetailInput::LONG,
ADDRESS_HOME_LINE1,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1) },
{ DetailInput::LONG,
ADDRESS_HOME_LINE2,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2) },
{ DetailInput::LONG,
ADDRESS_HOME_CITY,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY) },
{ DetailInput::SHORT,
ADDRESS_HOME_STATE,
IDS_AUTOFILL_FIELD_LABEL_STATE },
{ DetailInput::SHORT,
GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_STATE) },
{ DetailInput::SHORT_EOL,
ADDRESS_HOME_ZIP,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
{ DetailInput::NONE, ADDRESS_HOME_COUNTRY, 0 },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE) },
{ DetailInput::NONE, ADDRESS_HOME_COUNTRY },
};
const DetailInput kShippingPhoneInputs[] = {
{ DetailInput::LONG,
PHONE_HOME_WHOLE_NUMBER,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER) },
};
switch (dialog_section) {
......@@ -152,17 +185,34 @@ void BuildInputsForSection(DialogSection dialog_section,
break;
case SECTION_BILLING:
BuildInputs(kBillingInputs, arraysize(kBillingInputs), inputs);
if (IsI18nInputEnabled())
BuildI18nAddressInputs(ADDRESS_TYPE_BILLING, country_code, inputs);
else
BuildInputs(kBillingInputs, arraysize(kBillingInputs), inputs);
BuildInputs(kBillingPhoneInputs, arraysize(kBillingPhoneInputs), inputs);
BuildInputs(kEmailInputs, arraysize(kEmailInputs), inputs);
break;
case SECTION_CC_BILLING:
BuildInputs(kCCInputs, arraysize(kCCInputs), inputs);
BuildInputs(kBillingInputs, arraysize(kBillingInputs), inputs);
if (IsI18nInputEnabled())
BuildI18nAddressInputs(ADDRESS_TYPE_BILLING, country_code, inputs);
else
BuildInputs(kBillingInputs, arraysize(kBillingInputs), inputs);
BuildInputs(kBillingPhoneInputs, arraysize(kBillingPhoneInputs), inputs);
break;
case SECTION_SHIPPING:
BuildInputs(kShippingInputs, arraysize(kShippingInputs), inputs);
if (IsI18nInputEnabled())
BuildI18nAddressInputs(ADDRESS_TYPE_SHIPPING, country_code, inputs);
else
BuildInputs(kShippingInputs, arraysize(kShippingInputs), inputs);
BuildInputs(
kShippingPhoneInputs, arraysize(kShippingPhoneInputs), inputs);
break;
}
}
......
......@@ -20,6 +20,12 @@ class Address;
namespace autofill {
namespace common {
// The types of addresses this class supports building.
enum AddressType {
ADDRESS_TYPE_BILLING,
ADDRESS_TYPE_SHIPPING,
};
// Returns true if |input| should be shown when |field_type| has been requested.
bool InputTypeMatchesFieldType(const DetailInput& input,
const AutofillType& field_type);
......@@ -34,7 +40,11 @@ bool DetailInputMatchesField(DialogSection section,
bool IsCreditCardType(ServerFieldType type);
// Constructs |inputs| from template data for a given |dialog_section|.
void BuildInputsForSection(DialogSection dialog_section, DetailInputs* inputs);
// |country_country| specifies the country code that the inputs should be built
// for.
void BuildInputsForSection(DialogSection dialog_section,
const std::string& country_code,
DetailInputs* inputs);
// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
// to the |section|.
......
......@@ -29,6 +29,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/autofill_dialog_common.h"
#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
#include "chrome/browser/ui/autofill/autofill_dialog_view.h"
#include "chrome/browser/ui/autofill/data_model_wrapper.h"
#if !defined(OS_ANDROID)
......@@ -603,13 +604,20 @@ void AutofillDialogControllerImpl::Show() {
AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME);
}
// TODO(dbeam): use GetManager()->GetDefaultCountryCodeForNewAddress()
// instead when the country combobox is visible. http://crbug.com/331544
std::string country_code = "US";
common::BuildInputsForSection(SECTION_CC,
country_code,
&requested_cc_fields_);
common::BuildInputsForSection(SECTION_BILLING,
country_code,
&requested_billing_fields_);
common::BuildInputsForSection(SECTION_CC_BILLING,
country_code,
&requested_cc_billing_fields_);
common::BuildInputsForSection(SECTION_SHIPPING,
country_code,
&requested_shipping_fields_);
// Test whether we need to show the shipping section. If filling that section
......
......@@ -304,6 +304,7 @@ class TestAutofillDialogController
using AutofillDialogControllerImpl::AccountChooserModelForTesting;
using AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData;
using AutofillDialogControllerImpl::IsEditingExistingData;
using AutofillDialogControllerImpl::IsManuallyEditingSection;
using AutofillDialogControllerImpl::IsSubmitPausedOn;
using AutofillDialogControllerImpl::NOT_CHECKED;
using AutofillDialogControllerImpl::SignedInState;
......@@ -553,6 +554,44 @@ class AutofillDialogControllerTest : public ChromeRenderViewHostTestHarness {
return static_cast<SuggestionsMenuModel*>(model);
}
void SubmitAndVerifyShippingAndBillingResults() {
// Test after setting use billing for shipping.
UseBillingForShipping();
controller()->OnAccept();
ASSERT_EQ(20U, form_structure()->field_count());
EXPECT_EQ(ADDRESS_HOME_COUNTRY,
form_structure()->field(11)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_BILLING, form_structure()->field(11)->Type().group());
EXPECT_EQ(ADDRESS_HOME_COUNTRY,
form_structure()->field(18)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME, form_structure()->field(18)->Type().group());
base::string16 billing_country = form_structure()->field(11)->value;
EXPECT_EQ(2U, billing_country.size());
base::string16 shipping_country = form_structure()->field(18)->value;
EXPECT_EQ(2U, shipping_country.size());
EXPECT_FALSE(billing_country.empty());
EXPECT_FALSE(shipping_country.empty());
EXPECT_EQ(billing_country, shipping_country);
EXPECT_EQ(CREDIT_CARD_NAME,
form_structure()->field(1)->Type().GetStorableType());
base::string16 cc_name = form_structure()->field(1)->value;
EXPECT_EQ(NAME_FULL, form_structure()->field(6)->Type().GetStorableType());
EXPECT_EQ(NAME_BILLING, form_structure()->field(6)->Type().group());
base::string16 billing_name = form_structure()->field(6)->value;
EXPECT_EQ(NAME_FULL, form_structure()->field(13)->Type().GetStorableType());
EXPECT_EQ(NAME, form_structure()->field(13)->Type().group());
base::string16 shipping_name = form_structure()->field(13)->value;
EXPECT_FALSE(cc_name.empty());
EXPECT_FALSE(billing_name.empty());
EXPECT_FALSE(shipping_name.empty());
EXPECT_EQ(cc_name, billing_name);
EXPECT_EQ(cc_name, shipping_name);
}
TestAutofillDialogController* controller() { return controller_.get(); }
const FormStructure* form_structure() { return form_structure_; }
......@@ -1095,45 +1134,35 @@ TEST_F(AutofillDialogControllerTest, DontUseBillingAsShipping) {
// Test selecting UseBillingForShipping.
TEST_F(AutofillDialogControllerTest, UseBillingAsShipping) {
SwitchToAutofill();
AutofillProfile full_profile(test::GetVerifiedProfile());
AutofillProfile full_profile2(test::GetVerifiedProfile2());
CreditCard credit_card(test::GetVerifiedCreditCard());
controller()->GetTestingManager()->AddTestingProfile(&full_profile);
AutofillProfile full_profile2(test::GetVerifiedProfile2());
controller()->GetTestingManager()->AddTestingProfile(&full_profile2);
CreditCard credit_card(test::GetVerifiedCreditCard());
controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
// Test after setting use billing for shipping.
UseBillingForShipping();
ASSERT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
ASSERT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
controller()->OnAccept();
ASSERT_EQ(20U, form_structure()->field_count());
EXPECT_EQ(ADDRESS_HOME_STATE,
form_structure()->field(9)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_BILLING, form_structure()->field(9)->Type().group());
EXPECT_EQ(ADDRESS_HOME_STATE,
form_structure()->field(16)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME, form_structure()->field(16)->Type().group());
base::string16 billing_state = form_structure()->field(9)->value;
base::string16 shipping_state = form_structure()->field(16)->value;
EXPECT_FALSE(billing_state.empty());
EXPECT_FALSE(shipping_state.empty());
EXPECT_EQ(billing_state, shipping_state);
SubmitAndVerifyShippingAndBillingResults();
}
EXPECT_EQ(CREDIT_CARD_NAME,
form_structure()->field(1)->Type().GetStorableType());
base::string16 cc_name = form_structure()->field(1)->value;
EXPECT_EQ(NAME_FULL, form_structure()->field(6)->Type().GetStorableType());
EXPECT_EQ(NAME_BILLING, form_structure()->field(6)->Type().group());
base::string16 billing_name = form_structure()->field(6)->value;
EXPECT_EQ(NAME_FULL, form_structure()->field(13)->Type().GetStorableType());
EXPECT_EQ(NAME, form_structure()->field(13)->Type().group());
base::string16 shipping_name = form_structure()->field(13)->value;
TEST_F(AutofillDialogControllerTest, UseBillingAsShippingManualInput) {
SwitchToAutofill();
EXPECT_FALSE(cc_name.empty());
EXPECT_FALSE(billing_name.empty());
EXPECT_FALSE(shipping_name.empty());
EXPECT_EQ(cc_name, billing_name);
EXPECT_EQ(cc_name, shipping_name);
ASSERT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC));
ASSERT_TRUE(controller()->IsManuallyEditingSection(SECTION_BILLING));
CreditCard credit_card(test::GetVerifiedCreditCard());
FillInputs(SECTION_CC, credit_card);
AutofillProfile full_profile(test::GetVerifiedProfile());
FillInputs(SECTION_BILLING, full_profile);
SubmitAndVerifyShippingAndBillingResults();
}
// Tests that shipping and billing telephone fields are supported, and filled
......
// Copyright 2014 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.
#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "components/autofill/core/browser/field_types.h"
#include "grit/component_strings.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui_component.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/localization.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
namespace i18ninput {
namespace {
using i18n::addressinput::AddressField;
using i18n::addressinput::AddressUiComponent;
ServerFieldType GetServerType(AddressField address_field, bool billing) {
switch (address_field) {
case i18n::addressinput::COUNTRY:
return billing ? ADDRESS_BILLING_COUNTRY : ADDRESS_HOME_COUNTRY;
case i18n::addressinput::ADMIN_AREA:
return billing ? ADDRESS_BILLING_STATE : ADDRESS_HOME_STATE;
case i18n::addressinput::LOCALITY:
return billing ? ADDRESS_BILLING_CITY : ADDRESS_HOME_CITY;
case i18n::addressinput::DEPENDENT_LOCALITY:
return billing ? ADDRESS_BILLING_DEPENDENT_LOCALITY :
ADDRESS_HOME_DEPENDENT_LOCALITY;
case i18n::addressinput::POSTAL_CODE:
return billing ? ADDRESS_BILLING_ZIP : ADDRESS_HOME_ZIP;
case i18n::addressinput::SORTING_CODE:
return billing ? ADDRESS_BILLING_SORTING_CODE : ADDRESS_HOME_SORTING_CODE;
case i18n::addressinput::STREET_ADDRESS:
return billing ? ADDRESS_BILLING_LINE1 : ADDRESS_HOME_LINE1;
case i18n::addressinput::RECIPIENT:
return billing ? NAME_BILLING_FULL : NAME_FULL;
case i18n::addressinput::ORGANIZATION:
return COMPANY_NAME;
}
NOTREACHED();
return UNKNOWN_TYPE;
}
DetailInput::Length LengthFromHint(AddressUiComponent::LengthHint hint) {
if (hint == AddressUiComponent::HINT_SHORT)
return DetailInput::SHORT;
DCHECK_EQ(hint, AddressUiComponent::HINT_LONG);
return DetailInput::LONG;
}
} // namespace
bool Enabled() {
CommandLine* command_line = CommandLine::ForCurrentProcess();
return command_line->HasSwitch(::switches::kEnableAutofillAddressI18n);
}
void BuildAddressInputs(common::AddressType address_type,
const std::string& country_code,
DetailInputs* inputs) {
i18n::addressinput::Localization localization;
// TODO(dbeam): figure out how to include libaddressinput's translations into
// some .pak file so I can call |SetGetter(&l10n_util::GetStringUTF8)| here.
std::vector<AddressUiComponent> components(
i18n::addressinput::BuildComponents(country_code, localization));
const bool billing = address_type == common::ADDRESS_TYPE_BILLING;
for (size_t i = 0; i < components.size(); ++i) {
const AddressUiComponent& component = components[i];
if (component.field == i18n::addressinput::ORGANIZATION) {
// TODO(dbeam): figure out when we actually need this.
continue;
}
ServerFieldType server_type = GetServerType(component.field, billing);
DetailInput::Length length = LengthFromHint(component.length_hint);
base::string16 placeholder = base::UTF8ToUTF16(component.name);
DetailInput input = { length, server_type, placeholder };
inputs->push_back(input);
if (component.field == i18n::addressinput::STREET_ADDRESS) {
// TODO(dbeam): support more than 2 address lines. http://crbug.com/324889
ServerFieldType server_type =
billing ? ADDRESS_BILLING_LINE2 : ADDRESS_HOME_LINE2;
base::string16 placeholder = base::UTF8ToUTF16(component.name);
DetailInput input = { length, server_type, placeholder };
inputs->push_back(input);
}
}
ServerFieldType server_type =
billing ? ADDRESS_BILLING_COUNTRY : ADDRESS_HOME_COUNTRY;
base::string16 placeholder_text =
l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COUNTRY);
// TODO(dbeam): unhide so users can switch countries. http://crbug.com/331544
DetailInput input = { DetailInput::NONE, server_type, placeholder_text };
inputs->push_back(input);
}
} // namespace i18ninput
} // namespace autofill
// Copyright 2014 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.
#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_I18N_INPUT_H_
#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_I18N_INPUT_H_
#include "chrome/browser/ui/autofill/autofill_dialog_common.h"
#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
namespace autofill {
namespace i18ninput {
// Returns true if the internationalized address input is enabled.
bool Enabled();
// Builds internationalized address input fields for |country_code| and adds
// them (at most 13) to |inputs|. |address_type| is which kind of address to
// build (e.g. billing or shipping).
void BuildAddressInputs(common::AddressType address_type,
const std::string& country_code,
DetailInputs* inputs);
} // namespace i18ninput
} // namespace autofill
#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_I18N_INPUT_H_
// Copyright 2014 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.
#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
#include "base/command_line.h"
#include "chrome/common/chrome_switches.h"
#include "components/autofill/core/browser/field_types.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
namespace i18ninput {
namespace {
const size_t kNumberOfAddressLinesUS = 7;
void AppendSwitch() {
CommandLine* command_line = CommandLine::ForCurrentProcess();
command_line->AppendSwitch(::switches::kEnableAutofillAddressI18n);
ASSERT_TRUE(Enabled());
}
} // namespace
TEST(AutofillDialogI18nInput, DisabledByDefault) {
EXPECT_FALSE(Enabled());
}
TEST(AutofillDialogI18nInput, USShippingAddress) {
AppendSwitch();
DetailInputs inputs;
BuildAddressInputs(common::ADDRESS_TYPE_SHIPPING, "US", &inputs);
ASSERT_EQ(kNumberOfAddressLinesUS, inputs.size());
EXPECT_EQ(NAME_FULL, inputs[0].type);
EXPECT_EQ(ADDRESS_HOME_COUNTRY, inputs[kNumberOfAddressLinesUS - 1].type);
}
TEST(AutofillDialogI18nInput, USBillingAddress) {
AppendSwitch();
DetailInputs inputs;
BuildAddressInputs(common::ADDRESS_TYPE_BILLING, "US", &inputs);
ASSERT_EQ(kNumberOfAddressLinesUS, inputs.size());
EXPECT_EQ(NAME_BILLING_FULL, inputs[0].type);
EXPECT_EQ(ADDRESS_BILLING_COUNTRY, inputs[kNumberOfAddressLinesUS - 1].type);
}
TEST(AutofillDialogI18nInput, USCityStateAndZipCodeShareInputRow) {
AppendSwitch();
DetailInputs inputs;
BuildAddressInputs(common::ADDRESS_TYPE_SHIPPING, "US", &inputs);
ASSERT_EQ(kNumberOfAddressLinesUS, inputs.size());
// Inputs before or after [ City ] [ State ] [ Zip ] should be on other lines.
EXPECT_NE(inputs[2].length, DetailInput::SHORT);
const DetailInput& city = inputs[3];
ASSERT_EQ(ADDRESS_HOME_CITY, city.type);
EXPECT_EQ(city.length, DetailInput::SHORT);
const DetailInput& state = inputs[4];
ASSERT_EQ(ADDRESS_HOME_STATE, state.type);
EXPECT_EQ(state.length, DetailInput::SHORT);
const DetailInput& zip = inputs[5];
ASSERT_EQ(ADDRESS_HOME_ZIP, zip.type);
EXPECT_EQ(zip.length, DetailInput::SHORT);
EXPECT_NE(inputs[6].length, DetailInput::SHORT);
}
} // namespace i18ninput
} // namespace autofill
......@@ -28,9 +28,11 @@ class AutofillField;
// dialog.
struct DetailInput {
enum Length {
SHORT, // Short inputs share a line with other short inputs. [ CVC ][ Zip ]
LONG, // Long inputs will be given their own full line. [ City ]
NONE, // Input will not be shown.
SHORT, // Shares a line with other short inputs, like display: inline.
SHORT_EOL, // Like SHORT but starts a new line directly afterward. Used to
// separate groups of short inputs into different lines.
LONG, // Will be given its own full line, like display: block.
NONE, // Input will not be shown.
};
// Used to determine which inputs share lines when laying out.
......@@ -38,8 +40,8 @@ struct DetailInput {
ServerFieldType type;
// Placeholder text resource ID.
int placeholder_text_rid;
// Text shown when the input is at its default state (e.g. empty).
base::string16 placeholder_text;
// A number between 0 and 1.0 that describes how much of the horizontal space
// in the row should be allotted to this input. 0 is equivalent to 1.
......
......@@ -39,7 +39,7 @@ MockAutofillDialogViewDelegate::MockAutofillDialogViewDelegate() {
const DetailInput kCreditCardInputs[] = {
{ DetailInput::SHORT,
CREDIT_CARD_VERIFICATION_CODE,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC }
l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC) }
};
cc_default_inputs_.push_back(kCreditCardInputs[0]);
ON_CALL(*this, RequestedFieldsForSection(SECTION_CC))
......
......@@ -621,7 +621,7 @@ bool ShouldOverwriteComboboxes(autofill::DialogSection section,
base::scoped_nsobject<AutofillTextField> field(
[[AutofillTextField alloc] init]);
[[field cell] setPlaceholderString:
l10n_util::GetNSStringWithFixup(input.placeholder_text_rid)];
l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)];
NSString* tooltipText =
base::SysUTF16ToNSString(delegate_->TooltipForField(input.type));
if ([tooltipText length] > 0) {
......@@ -652,8 +652,10 @@ bool ShouldOverwriteComboboxes(autofill::DialogSection section,
}
layout->AddView(control);
if (input.length == autofill::DetailInput::LONG)
if (input.length == autofill::DetailInput::LONG ||
input.length == autofill::DetailInput::SHORT_EOL) {
++column_set_id;
}
}
[self updateFieldIcons];
......
......@@ -119,9 +119,7 @@ TEST_F(AutofillSectionContainerTest, OutputMatchesDefinition) {
using namespace testing;
const DetailInput kTestInputs[] = {
{ DetailInput::LONG,
EMAIL_ADDRESS,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
{ DetailInput::LONG, EMAIL_ADDRESS },
{ DetailInput::SHORT, CREDIT_CARD_EXP_MONTH },
};
autofill::MonthComboboxModel comboModel;
......@@ -184,9 +182,7 @@ TEST_F(AutofillSectionContainerTest, FieldsAreInitiallyValid) {
using namespace testing;
const DetailInput kTestInputs[] = {
{ DetailInput::LONG,
EMAIL_ADDRESS,
IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
{ DetailInput::LONG, EMAIL_ADDRESS },
{ DetailInput::SHORT, CREDIT_CARD_EXP_MONTH },
};
......@@ -214,8 +210,8 @@ TEST_F(AutofillSectionContainerTest, ControllerInformsValidity) {
using namespace testing;
const DetailInput kTestInputs[] = {
{ DetailInput::LONG, EMAIL_ADDRESS, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
{ DetailInput::SHORT, CREDIT_CARD_EXP_MONTH }
{ DetailInput::LONG, EMAIL_ADDRESS },
{ DetailInput::SHORT, CREDIT_CARD_EXP_MONTH },
};
MonthComboboxModel comboModel;
......
......@@ -1978,11 +1978,9 @@ views::View* AutofillDialogViews::InitInputsView(DialogSection section) {
SelectComboboxValueOrSetToDefault(combobox, input.initial_value);
view_to_add.reset(combobox);
} else {
DecoratedTextfield* field = new DecoratedTextfield(
input.initial_value,
l10n_util::GetStringUTF16(input.placeholder_text_rid),
this);
DecoratedTextfield* field = new DecoratedTextfield(input.initial_value,
input.placeholder_text,
this);
textfields->insert(std::make_pair(input.type, field));
view_to_add.reset(field);
}
......@@ -2025,8 +2023,10 @@ views::View* AutofillDialogViews::InitInputsView(DialogSection section) {
views::GridLayout::FILL, views::GridLayout::FILL,
1, 0);
if (input.length == DetailInput::LONG)
if (input.length == DetailInput::LONG ||
input.length == DetailInput::SHORT_EOL) {
++column_set_id;
}
}
SetIconsForSection(section);
......
......@@ -364,6 +364,8 @@
'browser/ui/autofill/autofill_dialog_controller.h',
'browser/ui/autofill/autofill_dialog_controller_impl.cc',
'browser/ui/autofill/autofill_dialog_controller_impl.h',
'browser/ui/autofill/autofill_dialog_i18n_input.cc',
'browser/ui/autofill/autofill_dialog_i18n_input.h',
'browser/ui/autofill/autofill_dialog_models.cc',
'browser/ui/autofill/autofill_dialog_models.h',
'browser/ui/autofill/autofill_dialog_sign_in_delegate.cc',
......@@ -3342,10 +3344,24 @@
['include', '^browser/ui/app_list/app_list_service_disabled.cc'],
],
}],
['enable_autofill_dialog!=1 or OS=="android"', {
['enable_autofill_dialog!=1', {
'sources!': [
'browser/ui/autofill/autofill_dialog_common.cc',
'browser/ui/autofill/autofill_dialog_common.h',
'browser/ui/autofill/data_model_wrapper.cc',
'browser/ui/autofill/data_model_wrapper.h',
],
}],
['enable_autofill_dialog==1 and OS!="android"', {
'dependencies': [
'../third_party/libaddressinput/libaddressinput.gyp:libaddressinput',
],
}, { # enable_autofill_dialog!=1 or OS=="android"
'sources!': [
'browser/ui/autofill/autofill_dialog_controller_impl.cc',
'browser/ui/autofill/autofill_dialog_controller_impl.h',
'browser/ui/autofill/autofill_dialog_i18n_input.cc',
'browser/ui/autofill/autofill_dialog_i18n_input.h',
'browser/ui/autofill/autofill_dialog_view.h',
'browser/ui/autofill/autofill_dialog_view.cc',
'browser/ui/autofill/autofill_dialog_view_delegate.h',
......
......@@ -1423,6 +1423,7 @@
'browser/ui/ash/window_positioner_unittest.cc',
'browser/ui/autofill/account_chooser_model_unittest.cc',
'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
'browser/ui/autofill/autofill_dialog_i18n_input_unittest.cc',
'browser/ui/autofill/autofill_dialog_models_unittest.cc',
'browser/ui/autofill/autofill_dialog_types_unittest.cc',
'browser/ui/autofill/autofill_popup_controller_unittest.cc',
......@@ -2235,6 +2236,8 @@
'browser/ui/autofill/account_chooser_model_unittest.cc',
'browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc',
'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
'browser/ui/autofill/autofill_dialog_i18n_input_unittest.cc',
'browser/ui/autofill/data_model_wrapper_unittest.cc',
'browser/ui/autofill/mock_autofill_dialog_view_delegate.cc',
'browser/ui/autofill/mock_autofill_dialog_view_delegate.h',
'browser/ui/autofill/test_autofill_credit_card_bubble.cc',
......
......@@ -583,6 +583,9 @@ const char kEnableAsyncDns[] = "enable-async-dns";
// HttpAuthHandlerNegotiate::CreateSPN for more background.
const char kEnableAuthNegotiatePort[] = "enable-auth-negotiate-port";
// Enables the i18n address input widget for the requestAutocomplete() dialog.
const char kEnableAutofillAddressI18n[] = "enable-autofill-address-i18n";
// Enable using a public suffix based domain matching for autofill of passwords.
const char kEnablePasswordAutofillPublicSuffixDomainMatching[] =
"enable-password-autofill-public-suffix-domain-matching";
......
......@@ -168,6 +168,7 @@ extern const char kEnableAppWindowControls[];
extern const char kEnableAppsShowOnFirstPaint[];
extern const char kEnableAsyncDns[];
extern const char kEnableAuthNegotiatePort[];
extern const char kEnableAutofillAddressI18n[];
extern const char kEnableAutologin[];
extern const char kEnableBenchmarking[];
extern const char kEnableClientHints[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment