Commit ef5140bd authored by Elizabeth Popova's avatar Elizabeth Popova Committed by Chromium LUCI CQ

[Android][Autofill] Add honorific prefix field to AddressEditor

The new input is placed above the name field and only shown if Address
Editor is opened from Autofill Settings (purpose = AUTOFILL_SETTINGS)
and kAutofillEnableUIForHonorificPrefixesInSettings feature is enabled.

The entered value will not be saved, because honorifics are temporarily
disabled (crbug/1113617).

Screenshot: https://storage.cloud.google.com/chromium-translation-screenshots/4dcf597fed4da10035e80a4f22cf4a73b927a84e

Bug: 1141884
Change-Id: I2ff12dfb6935d576e3ca73c3b3cdaddd75b82b2e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2571759Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: default avatarChristoph Schwering <schwering@google.com>
Commit-Queue: Elizabeth Popova <lizapopova@google.com>
Cr-Commit-Position: refs/heads/master@{#834665}
parent 1d58e1c4
...@@ -214,6 +214,7 @@ public class PersonalDataManager { ...@@ -214,6 +214,7 @@ public class PersonalDataManager {
return mOrigin; return mOrigin;
} }
@CalledByNative("AutofillProfile")
public String getHonorificPrefix() { public String getHonorificPrefix() {
return mHonorificPrefix; return mHonorificPrefix;
} }
......
...@@ -25,6 +25,7 @@ import org.chromium.chrome.browser.autofill.prefeditor.EditorModel; ...@@ -25,6 +25,7 @@ import org.chromium.chrome.browser.autofill.prefeditor.EditorModel;
import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge; import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge;
import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressField; import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressField;
import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressUiComponent; import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressUiComponent;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.payments.mojom.AddressErrors; import org.chromium.payments.mojom.AddressErrors;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
...@@ -63,6 +64,8 @@ public class AddressEditor ...@@ -63,6 +64,8 @@ public class AddressEditor
@Nullable @Nullable
private EditorFieldModel mCountryField; private EditorFieldModel mCountryField;
@Nullable @Nullable
private EditorFieldModel mHonorificField;
@Nullable
private EditorFieldModel mPhoneField; private EditorFieldModel mPhoneField;
@Nullable @Nullable
private EditorFieldModel mEmailField; private EditorFieldModel mEmailField;
...@@ -112,6 +115,11 @@ public class AddressEditor ...@@ -112,6 +115,11 @@ public class AddressEditor
mAddressErrors = errors; mAddressErrors = errors;
} }
private boolean isUIForHonorificPrefixesEnabled() {
return ChromeFeatureList.isEnabled(
ChromeFeatureList.AUTOFILL_ENABLE_UI_FOR_HONORIFIC_PREFIXES_IN_SETTINGS);
}
private String getAddressError(int field) { private String getAddressError(int field) {
if (mAddressErrors == null) return null; if (mAddressErrors == null) return null;
...@@ -152,6 +160,7 @@ public class AddressEditor ...@@ -152,6 +160,7 @@ public class AddressEditor
* Builds and shows an editor model with the following fields. * Builds and shows an editor model with the following fields.
* *
* [ country dropdown ] <----- country dropdown is always present. * [ country dropdown ] <----- country dropdown is always present.
* [ honorific field ] <----- above name, present if purpose is Purpose.AUTOFILL_SETTINGS.
* [ an address field ] \ * [ an address field ] \
* [ an address field ] \ * [ an address field ] \
* ... <-- field order, presence, required, and labels depend on country. * ... <-- field order, presence, required, and labels depend on country.
...@@ -226,6 +235,17 @@ public class AddressEditor ...@@ -226,6 +235,17 @@ public class AddressEditor
mPhoneValidator.setCountryCode(mCountryField.getValue().toString()); mPhoneValidator.setCountryCode(mCountryField.getValue().toString());
mPhoneFormatter.setCountryCode(mCountryField.getValue().toString()); mPhoneFormatter.setCountryCode(mCountryField.getValue().toString());
// Honorific prefix is present only for autofill settings.
if (mPurpose == Purpose.AUTOFILL_SETTINGS && isUIForHonorificPrefixesEnabled()) {
if (mHonorificField == null) {
mHonorificField = EditorFieldModel.createTextInput();
mHonorificField.setLabel(
mContext.getString(R.string.autofill_profile_editor_honorific_prefix));
}
// Retrieve and set the honorific prefix value.
mHonorificField.setValue(mProfile.getHonorificPrefix());
}
// There's a finite number of fields for address editing. Changing the country will re-order // There's a finite number of fields for address editing. Changing the country will re-order
// and relabel the fields. The meaning of each field remains the same. // and relabel the fields. The meaning of each field remains the same.
if (mAddressFields.isEmpty()) { if (mAddressFields.isEmpty()) {
...@@ -333,6 +353,9 @@ public class AddressEditor ...@@ -333,6 +353,9 @@ public class AddressEditor
profile.setCountryCode(mCountryField.getValue().toString()); profile.setCountryCode(mCountryField.getValue().toString());
profile.setPhoneNumber(mPhoneField.getValue().toString()); profile.setPhoneNumber(mPhoneField.getValue().toString());
if (mEmailField != null) profile.setEmailAddress(mEmailField.getValue().toString()); if (mEmailField != null) profile.setEmailAddress(mEmailField.getValue().toString());
if (mHonorificField != null) {
profile.setHonorificPrefix(mHonorificField.getValue().toString());
}
// Autofill profile bridge normalizes the language code for the autofill profile. // Autofill profile bridge normalizes the language code for the autofill profile.
profile.setLanguageCode(mAutofillProfileBridge.getCurrentBestLanguageCode()); profile.setLanguageCode(mAutofillProfileBridge.getCurrentBestLanguageCode());
...@@ -507,6 +530,11 @@ public class AddressEditor ...@@ -507,6 +530,11 @@ public class AddressEditor
for (int i = 0; i < mAddressUiComponents.size(); i++) { for (int i = 0; i < mAddressUiComponents.size(); i++) {
AddressUiComponent component = mAddressUiComponents.get(i); AddressUiComponent component = mAddressUiComponents.get(i);
// Honorific prefix should go before name.
if (component.id == AddressField.RECIPIENT && mHonorificField != null) {
mEditor.addField(mHonorificField);
}
EditorFieldModel field = mAddressFields.get(component.id); EditorFieldModel field = mAddressFields.get(component.id);
// Labels depend on country, e.g., state is called province in some countries. These are // Labels depend on country, e.g., state is called province in some countries. These are
......
...@@ -15,17 +15,20 @@ import org.junit.Assert; ...@@ -15,17 +15,20 @@ import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.Criteria;
import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.CriteriaHelper;
import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.autofill.AutofillTestHelper; import org.chromium.chrome.browser.autofill.AutofillTestHelper;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.settings.SettingsActivity; import org.chromium.chrome.browser.settings.SettingsActivity;
import org.chromium.chrome.browser.settings.SettingsActivityTestRule; import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.KeyboardVisibilityDelegate; import org.chromium.ui.KeyboardVisibilityDelegate;
...@@ -36,13 +39,15 @@ import java.util.concurrent.TimeoutException; ...@@ -36,13 +39,15 @@ import java.util.concurrent.TimeoutException;
* Unit test suite for AutofillProfilesFragment. * Unit test suite for AutofillProfilesFragment.
*/ */
@RunWith(BaseJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
public class AutofillProfilesFragmentTest { public class AutofillProfilesFragmentTest {
@Rule @Rule
public final AutofillTestRule rule = new AutofillTestRule(); public final AutofillTestRule rule = new AutofillTestRule();
@Rule @Rule
public final SettingsActivityTestRule<AutofillProfilesFragment> mSettingsActivityTestRule = public final SettingsActivityTestRule<AutofillProfilesFragment> mSettingsActivityTestRule =
new SettingsActivityTestRule<>(AutofillProfilesFragment.class); new SettingsActivityTestRule<>(AutofillProfilesFragment.class);
@Rule
public final TestRule mFeaturesProcessorRule = new Features.JUnitProcessor();
@Before @Before
public void setUp() throws TimeoutException { public void setUp() throws TimeoutException {
...@@ -66,6 +71,8 @@ public class AutofillProfilesFragmentTest { ...@@ -66,6 +71,8 @@ public class AutofillProfilesFragmentTest {
@Test @Test
@MediumTest @MediumTest
@Feature({"Preferences"}) @Feature({"Preferences"})
@Features.
EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_UI_FOR_HONORIFIC_PREFIXES_IN_SETTINGS})
public void testAddProfile() throws Exception { public void testAddProfile() throws Exception {
SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity();
AutofillProfilesFragment autofillProfileFragment = AutofillProfilesFragment autofillProfileFragment =
...@@ -82,8 +89,8 @@ public class AutofillProfilesFragmentTest { ...@@ -82,8 +89,8 @@ public class AutofillProfilesFragmentTest {
// Add a profile. // Add a profile.
updatePreferencesAndWait(autofillProfileFragment, addProfile, updatePreferencesAndWait(autofillProfileFragment, addProfile,
new String[] {"Alice Doe", "Google", "111 Added St", "Los Angeles", "CA", "90291", new String[] {"Ms.", "Alice Doe", "Google", "111 Added St", "Los Angeles", "CA",
"650-253-0000", "add@profile.com"}, "90291", "650-253-0000", "add@profile.com"},
R.id.editor_dialog_done_button, false); R.id.editor_dialog_done_button, false);
Assert.assertEquals(7 /* One toggle + one add button + five profiles. */, Assert.assertEquals(7 /* One toggle + one add button + five profiles. */,
...@@ -98,6 +105,8 @@ public class AutofillProfilesFragmentTest { ...@@ -98,6 +105,8 @@ public class AutofillProfilesFragmentTest {
@Test @Test
@MediumTest @MediumTest
@Feature({"Preferences"}) @Feature({"Preferences"})
@Features.
EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_UI_FOR_HONORIFIC_PREFIXES_IN_SETTINGS})
public void testAddIncompletedProfile() throws Exception { public void testAddIncompletedProfile() throws Exception {
SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity();
AutofillProfilesFragment autofillProfileFragment = AutofillProfilesFragment autofillProfileFragment =
...@@ -113,7 +122,7 @@ public class AutofillProfilesFragmentTest { ...@@ -113,7 +122,7 @@ public class AutofillProfilesFragmentTest {
Assert.assertNotNull(addProfile); Assert.assertNotNull(addProfile);
// Add an incomplete profile. // Add an incomplete profile.
updatePreferencesAndWait(autofillProfileFragment, addProfile, new String[] {"Mike Doe"}, updatePreferencesAndWait(autofillProfileFragment, addProfile, new String[] {"", "Mike Doe"},
R.id.editor_dialog_done_button, false); R.id.editor_dialog_done_button, false);
// Incomplete profile should still be added. // Incomplete profile should still be added.
...@@ -128,6 +137,8 @@ public class AutofillProfilesFragmentTest { ...@@ -128,6 +137,8 @@ public class AutofillProfilesFragmentTest {
@Test @Test
@MediumTest @MediumTest
@Feature({"Preferences"}) @Feature({"Preferences"})
@Features.
EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_UI_FOR_HONORIFIC_PREFIXES_IN_SETTINGS})
public void testAddProfileWithInvalidPhone() throws Exception { public void testAddProfileWithInvalidPhone() throws Exception {
SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity();
AutofillProfilesFragment autofillProfileFragment = AutofillProfilesFragment autofillProfileFragment =
...@@ -144,7 +155,8 @@ public class AutofillProfilesFragmentTest { ...@@ -144,7 +155,8 @@ public class AutofillProfilesFragmentTest {
// Try to add a profile with invalid phone. // Try to add a profile with invalid phone.
updatePreferencesAndWait(autofillProfileFragment, addProfile, updatePreferencesAndWait(autofillProfileFragment, addProfile,
new String[] {"", "", "", "", "", "", "123"}, R.id.editor_dialog_done_button, true); new String[] {"", "", "", "", "", "", "", "123"}, R.id.editor_dialog_done_button,
true);
activity.finish(); activity.finish();
} }
...@@ -183,6 +195,8 @@ public class AutofillProfilesFragmentTest { ...@@ -183,6 +195,8 @@ public class AutofillProfilesFragmentTest {
@Test @Test
@MediumTest @MediumTest
@Feature({"Preferences"}) @Feature({"Preferences"})
@Features.
EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_UI_FOR_HONORIFIC_PREFIXES_IN_SETTINGS})
public void testEditProfile() throws Exception { public void testEditProfile() throws Exception {
SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity();
AutofillProfilesFragment autofillProfileFragment = AutofillProfilesFragment autofillProfileFragment =
...@@ -199,8 +213,8 @@ public class AutofillProfilesFragmentTest { ...@@ -199,8 +213,8 @@ public class AutofillProfilesFragmentTest {
// Edit a profile. // Edit a profile.
updatePreferencesAndWait(autofillProfileFragment, johnProfile, updatePreferencesAndWait(autofillProfileFragment, johnProfile,
new String[] {"Emily Doe", "Google", "111 Edited St", "Los Angeles", "CA", "90291", new String[] {"Dr.", "Emily Doe", "Google", "111 Edited St", "Los Angeles", "CA",
"650-253-0000", "edit@profile.com"}, "90291", "650-253-0000", "edit@profile.com"},
R.id.editor_dialog_done_button, false); R.id.editor_dialog_done_button, false);
// Check if the preferences are updated correctly. // Check if the preferences are updated correctly.
Assert.assertEquals(6 /* One toggle + one add button + four profiles. */, Assert.assertEquals(6 /* One toggle + one add button + four profiles. */,
......
...@@ -323,6 +323,8 @@ void PersonalDataManagerAndroid::PopulateNativeProfileFromJava( ...@@ -323,6 +323,8 @@ void PersonalDataManagerAndroid::PopulateNativeProfileFromJava(
AutofillType(NAME_FULL), AutofillType(NAME_FULL),
ConvertJavaStringToUTF16(Java_AutofillProfile_getFullName(env, jprofile)), ConvertJavaStringToUTF16(Java_AutofillProfile_getFullName(env, jprofile)),
g_browser_process->GetApplicationLocale()); g_browser_process->GetApplicationLocale());
MaybeSetRawInfo(profile, autofill::NAME_HONORIFIC_PREFIX,
Java_AutofillProfile_getHonorificPrefix(env, jprofile));
MaybeSetRawInfo(profile, autofill::COMPANY_NAME, MaybeSetRawInfo(profile, autofill::COMPANY_NAME,
Java_AutofillProfile_getCompanyName(env, jprofile)); Java_AutofillProfile_getCompanyName(env, jprofile));
MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_STREET_ADDRESS, MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_STREET_ADDRESS,
......
...@@ -77,6 +77,7 @@ const base::Feature* kFeaturesExposedToJava[] = { ...@@ -77,6 +77,7 @@ const base::Feature* kFeaturesExposedToJava[] = {
&autofill::features::kAutofillRefreshStyleAndroid, &autofill::features::kAutofillRefreshStyleAndroid,
&autofill::features::kAutofillEnableCardNicknameManagement, &autofill::features::kAutofillEnableCardNicknameManagement,
&autofill::features::kAutofillEnableGoogleIssuedCard, &autofill::features::kAutofillEnableGoogleIssuedCard,
&autofill::features::kAutofillEnableUIForHonorificPrefixesInSettings,
&autofill_assistant::features::kAutofillAssistant, &autofill_assistant::features::kAutofillAssistant,
&autofill_assistant::features::kAutofillAssistantChromeEntry, &autofill_assistant::features::kAutofillAssistantChromeEntry,
&autofill_assistant::features::kAutofillAssistantDirectActions, &autofill_assistant::features::kAutofillAssistantDirectActions,
......
...@@ -205,6 +205,8 @@ public abstract class ChromeFeatureList { ...@@ -205,6 +205,8 @@ public abstract class ChromeFeatureList {
"AutofillEnablePasswordInfoBarAccountIndicationFooter"; "AutofillEnablePasswordInfoBarAccountIndicationFooter";
public static final String AUTOFILL_ENABLE_SAVE_CARD_INFO_BAR_ACCOUNT_INDICATION_FOOTER = public static final String AUTOFILL_ENABLE_SAVE_CARD_INFO_BAR_ACCOUNT_INDICATION_FOOTER =
"AutofillEnableSaveCardInfoBarAccountIndicationFooter"; "AutofillEnableSaveCardInfoBarAccountIndicationFooter";
public static final String AUTOFILL_ENABLE_UI_FOR_HONORIFIC_PREFIXES_IN_SETTINGS =
"AutofillEnableUIForHonorificPrefixesInSettings";
public static final String ADJUST_WEBAPK_INSTALLATION_SPACE = "AdjustWebApkInstallationSpace"; public static final String ADJUST_WEBAPK_INSTALLATION_SPACE = "AdjustWebApkInstallationSpace";
public static final String ANDROID_DEFAULT_BROWSER_PROMO = "AndroidDefaultBrowserPromo"; public static final String ANDROID_DEFAULT_BROWSER_PROMO = "AndroidDefaultBrowserPromo";
public static final String ANDROID_LAYOUT_CHANGE_TAB_REPARENT = public static final String ANDROID_LAYOUT_CHANGE_TAB_REPARENT =
......
...@@ -464,6 +464,9 @@ CHAR-LIMIT guidelines: ...@@ -464,6 +464,9 @@ CHAR-LIMIT guidelines:
<message name="IDS_AUTOFILL_PROFILE_EDITOR_COUNTRY" desc="Label for a spinner input field containing a list of countries or regions [CHAR-LIMIT=32]"> <message name="IDS_AUTOFILL_PROFILE_EDITOR_COUNTRY" desc="Label for a spinner input field containing a list of countries or regions [CHAR-LIMIT=32]">
Country/Region Country/Region
</message> </message>
<message name="IDS_AUTOFILL_PROFILE_EDITOR_HONORIFIC_PREFIX" desc="Label for text input field containing a title that can be auto-filled by Chrome. [CHAR-LIMIT=32]" meaning="A 'Title' field in a web form could be a prefix like Ms., Mx., or Dr. or a position held, like Captain or Rabbi.">
Title
</message>
<message name="IDS_AUTOFILL_PROFILE_EDITOR_EMAIL_ADDRESS" desc="Label for text input field containing an e-mail address. [CHAR-LIMIT=32]"> <message name="IDS_AUTOFILL_PROFILE_EDITOR_EMAIL_ADDRESS" desc="Label for text input field containing an e-mail address. [CHAR-LIMIT=32]">
Email Email
</message> </message>
......
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