Commit 71f8a9fc authored by sandromaggi's avatar sandromaggi Committed by Commit Bot

[Autofill Assistant] Split profiles into usage cases.

Previously the source for contacts and shipping addresses was the same
sorted list of profiles. There may be cases where we want to sort them
differently, which is enabled by splitting the list in two.

This CL also moves the transformation logic from CreditCard / Profile
to their destination objects (AutofillContact, AutofillAddress,
AutofillPaymentInstrument) from the DataBinder to native/model
directly.

Bug: b/144005336
Change-Id: I644d4b52f962582a87b8aabce5e55066e3356481
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1992082
Commit-Queue: Sandro Maggi <sandromaggi@google.com>
Auto-Submit: Sandro Maggi <sandromaggi@google.com>
Reviewed-by: default avatarClemens Arbesser <arbesser@google.com>
Cr-Commit-Position: refs/heads/master@{#730165}
parent 0e9ae106
......@@ -5,15 +5,11 @@
package org.chromium.chrome.browser.autofill_assistant.user_data;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import org.chromium.base.task.PostTask;
import org.chromium.chrome.browser.ChromeVersionInfo;
import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.autofill.prefeditor.EditorDialog;
import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSectionContainer;
import org.chromium.chrome.browser.payments.AddressEditor;
......@@ -93,10 +89,6 @@ class AssistantCollectUserDataBinder
mDividerTag = dividerTag;
mActivity = activity;
}
public Context getContext() {
return mActivity;
}
}
@Override
......@@ -215,38 +207,35 @@ class AssistantCollectUserDataBinder
*/
private boolean updateSectionContents(
AssistantCollectUserDataModel model, PropertyKey propertyKey, ViewHolder view) {
if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS
if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS
|| propertyKey == AssistantCollectUserDataModel.WEB_CONTENTS) {
WebContents webContents = model.get(AssistantCollectUserDataModel.WEB_CONTENTS);
List<AssistantCollectUserDataModel.PaymentTuple> paymentTuples =
model.get(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS);
List<AutofillPaymentInstrument> availablePaymentMethods;
if (webContents != null && paymentTuples != null) {
availablePaymentMethods =
getPaymentInstrumentsFromPaymentTuples(webContents, paymentTuples);
} else {
availablePaymentMethods = Collections.emptyList();
if (model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
List<AutofillPaymentInstrument> paymentInstruments;
if (model.get(AssistantCollectUserDataModel.WEB_CONTENTS) == null) {
paymentInstruments = Collections.emptyList();
} else {
paymentInstruments =
model.get(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS);
}
view.mPaymentMethodSection.onAvailablePaymentMethodsChanged(paymentInstruments);
}
view.mPaymentMethodSection.onAvailablePaymentMethodsChanged(availablePaymentMethods);
return true;
} else if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_PROFILES) {
List<PersonalDataManager.AutofillProfile> autofillProfiles =
model.get(AssistantCollectUserDataModel.AVAILABLE_PROFILES);
if (autofillProfiles == null) {
autofillProfiles = Collections.emptyList();
}
} else if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_CONTACTS) {
if (shouldShowContactDetails(model)) {
view.mContactDetailsSection.onProfilesChanged(autofillProfiles,
model.get(AssistantCollectUserDataModel.REQUEST_EMAIL),
model.get(AssistantCollectUserDataModel.REQUEST_NAME),
model.get(AssistantCollectUserDataModel.REQUEST_PHONE));
}
if (model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
view.mPaymentMethodSection.onProfilesChanged(autofillProfiles);
view.mContactDetailsSection.onContactsChanged(
model.get(AssistantCollectUserDataModel.AVAILABLE_CONTACTS));
}
return true;
} else if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_SHIPPING_ADDRESSES) {
if (model.get(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS)) {
view.mShippingAddressSection.onProfilesChanged(autofillProfiles);
view.mShippingAddressSection.onAddressesChanged(
model.get(AssistantCollectUserDataModel.AVAILABLE_SHIPPING_ADDRESSES));
}
return true;
} else if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_BILLING_ADDRESSES) {
if (model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
view.mPaymentMethodSection.onAddressesChanged(
model.get(AssistantCollectUserDataModel.AVAILABLE_BILLING_ADDRESSES));
}
return true;
} else if (propertyKey == AssistantCollectUserDataModel.REQUIRE_BILLING_POSTAL_CODE
......@@ -376,10 +365,10 @@ class AssistantCollectUserDataBinder
*/
private boolean updateSectionSelectedItem(
AssistantCollectUserDataModel model, PropertyKey propertyKey, ViewHolder view) {
if (propertyKey == AssistantCollectUserDataModel.SHIPPING_ADDRESS) {
if (propertyKey == AssistantCollectUserDataModel.SELECTED_SHIPPING_ADDRESS) {
if (model.get(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS)) {
AutofillAddress shippingAddress = getAddressFromProfile(view.getContext(),
model.get(AssistantCollectUserDataModel.SHIPPING_ADDRESS));
AutofillAddress shippingAddress =
model.get(AssistantCollectUserDataModel.SELECTED_SHIPPING_ADDRESS);
if (shippingAddress != null) {
view.mShippingAddressSection.addOrUpdateItem(
shippingAddress, /* select= */ true);
......@@ -387,11 +376,10 @@ class AssistantCollectUserDataBinder
// No need to reset selection if null, this will be handled by setItems().
}
return true;
} else if (propertyKey == AssistantCollectUserDataModel.PAYMENT_METHOD) {
} else if (propertyKey == AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT) {
if (model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
AutofillPaymentInstrument paymentInstrument = getPaymentInstrumentFromPaymentTuple(
model.get(AssistantCollectUserDataModel.WEB_CONTENTS),
model.get(AssistantCollectUserDataModel.PAYMENT_METHOD));
AutofillPaymentInstrument paymentInstrument =
model.get(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT);
if (paymentInstrument != null) {
view.mPaymentMethodSection.addOrUpdateItem(
paymentInstrument, /* select= */ true);
......@@ -399,13 +387,10 @@ class AssistantCollectUserDataBinder
// No need to reset selection if null, this will be handled by setItems().
}
return true;
} else if (propertyKey == AssistantCollectUserDataModel.CONTACT_DETAILS) {
} else if (propertyKey == AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS) {
if (shouldShowContactDetails(model)) {
AutofillContact contact = getContactFromProfile(view.getContext(),
model.get(AssistantCollectUserDataModel.CONTACT_DETAILS),
model.get(AssistantCollectUserDataModel.REQUEST_NAME),
model.get(AssistantCollectUserDataModel.REQUEST_PHONE),
model.get(AssistantCollectUserDataModel.REQUEST_EMAIL));
AutofillContact contact =
model.get(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS);
if (contact != null) {
view.mContactDetailsSection.addOrUpdateItem(contact, /* select= */ true);
}
......@@ -616,55 +601,4 @@ class AssistantCollectUserDataBinder
return methodData;
}
private List<AutofillPaymentInstrument> getPaymentInstrumentsFromPaymentTuples(
WebContents webContents,
List<AssistantCollectUserDataModel.PaymentTuple> paymentTuples) {
List<AutofillPaymentInstrument> paymentInstruments = new ArrayList<>(paymentTuples.size());
for (AssistantCollectUserDataModel.PaymentTuple tuple : paymentTuples) {
paymentInstruments.add(new AutofillPaymentInstrument(webContents, tuple.getCreditCard(),
tuple.getBillingAddress(), MethodStrings.BASIC_CARD,
/* matchesMerchantCardTypeExactly= */ true));
}
return paymentInstruments;
}
@Nullable
private AutofillAddress getAddressFromProfile(
Context context, @Nullable PersonalDataManager.AutofillProfile profile) {
if (profile == null) {
return null;
}
return new AutofillAddress(context, profile);
}
@Nullable
private AutofillContact getContactFromProfile(Context context,
@Nullable PersonalDataManager.AutofillProfile profile, boolean requestName,
boolean requestPhone, boolean requestEmail) {
if (profile == null) {
return null;
}
ContactEditor editor = new ContactEditor(requestName, requestPhone, requestEmail, false);
String name = profile.getFullName();
String phone = profile.getPhoneNumber();
String email = profile.getEmailAddress();
return new AutofillContact(context, profile, name, phone, email,
editor.checkContactCompletionStatus(name, phone, email), requestName, requestPhone,
requestEmail);
}
@Nullable
private AutofillPaymentInstrument getPaymentInstrumentFromPaymentTuple(
@Nullable WebContents webContents,
@Nullable AssistantCollectUserDataModel.PaymentTuple paymentTuple) {
if (webContents == null || paymentTuple == null) {
return null;
}
return new AutofillPaymentInstrument(webContents, paymentTuple.getCreditCard(),
paymentTuple.getBillingAddress(), MethodStrings.BASIC_CARD,
/* matchesMerchantCardTypeExactly= */ true);
}
}
......@@ -4,7 +4,9 @@
package org.chromium.chrome.browser.autofill_assistant.user_data;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.view.View;
import org.chromium.base.annotations.CalledByNative;
......@@ -16,11 +18,17 @@ import org.chromium.chrome.browser.autofill_assistant.user_data.additional_secti
import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputSection;
import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputSection.TextInputFactory;
import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputType;
import org.chromium.chrome.browser.payments.AutofillAddress;
import org.chromium.chrome.browser.payments.AutofillContact;
import org.chromium.chrome.browser.payments.AutofillPaymentInstrument;
import org.chromium.chrome.browser.payments.ContactEditor;
import org.chromium.components.payments.MethodStrings;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.modelutil.PropertyModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
......@@ -30,31 +38,6 @@ import java.util.List;
public class AssistantCollectUserDataModel extends PropertyModel {
// TODO(crbug.com/806868): Add |setSelectedLogin|.
/**
* This class holds a the credit card and billing address information required to create an
* {@code AutofillPaymentInstrument}.
*/
public static class PaymentTuple {
private final PersonalDataManager.CreditCard mCreditCard;
@Nullable
private final PersonalDataManager.AutofillProfile mBillingAddress;
public PaymentTuple(PersonalDataManager.CreditCard creditCard,
@Nullable PersonalDataManager.AutofillProfile billingAddress) {
mCreditCard = creditCard;
mBillingAddress = billingAddress;
}
public PersonalDataManager.CreditCard getCreditCard() {
return mCreditCard;
}
@Nullable
public PersonalDataManager.AutofillProfile getBillingAddress() {
return mBillingAddress;
}
}
public static final WritableObjectPropertyKey<AssistantCollectUserDataDelegate> DELEGATE =
new WritableObjectPropertyKey<>();
......@@ -65,16 +48,16 @@ public class AssistantCollectUserDataModel extends PropertyModel {
public static final WritableBooleanPropertyKey VISIBLE = new WritableBooleanPropertyKey();
/** The chosen shipping address. */
public static final WritableObjectPropertyKey<PersonalDataManager.AutofillProfile>
SHIPPING_ADDRESS = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<AutofillAddress> SELECTED_SHIPPING_ADDRESS =
new WritableObjectPropertyKey<>();
/** The chosen payment method (including billing address). */
public static final WritableObjectPropertyKey<AssistantCollectUserDataModel.PaymentTuple>
PAYMENT_METHOD = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<AutofillPaymentInstrument>
SELECTED_PAYMENT_INSTRUMENT = new WritableObjectPropertyKey<>();
/** The chosen contact details. */
public static final WritableObjectPropertyKey<PersonalDataManager.AutofillProfile>
CONTACT_DETAILS = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<AutofillContact> SELECTED_CONTACT_DETAILS =
new WritableObjectPropertyKey<>();
/** The login section title. */
public static final WritableObjectPropertyKey<String> LOGIN_SECTION_TITLE =
......@@ -101,11 +84,17 @@ public class AssistantCollectUserDataModel extends PropertyModel {
public static final WritableBooleanPropertyKey REQUEST_LOGIN_CHOICE =
new WritableBooleanPropertyKey();
public static final WritableObjectPropertyKey<List<PersonalDataManager.AutofillProfile>>
AVAILABLE_PROFILES = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<List<AutofillAddress>>
AVAILABLE_BILLING_ADDRESSES = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<List<AutofillContact>> AVAILABLE_CONTACTS =
new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<List<AssistantCollectUserDataModel.PaymentTuple>>
AVAILABLE_AUTOFILL_PAYMENT_METHODS = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<List<AutofillAddress>>
AVAILABLE_SHIPPING_ADDRESSES = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<List<AutofillPaymentInstrument>>
AVAILABLE_PAYMENT_INSTRUMENTS = new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<List<String>> SUPPORTED_BASIC_CARD_NETWORKS =
new WritableObjectPropertyKey<>();
......@@ -158,11 +147,12 @@ public class AssistantCollectUserDataModel extends PropertyModel {
new WritableObjectPropertyKey<>();
public AssistantCollectUserDataModel() {
super(DELEGATE, WEB_CONTENTS, VISIBLE, SHIPPING_ADDRESS, PAYMENT_METHOD, CONTACT_DETAILS,
LOGIN_SECTION_TITLE, SELECTED_LOGIN, TERMS_STATUS, REQUEST_NAME, REQUEST_EMAIL,
REQUEST_PHONE, REQUEST_SHIPPING_ADDRESS, REQUEST_PAYMENT,
ACCEPT_TERMS_AND_CONDITIONS_TEXT, SHOW_TERMS_AS_CHECKBOX, REQUEST_LOGIN_CHOICE,
AVAILABLE_PROFILES, AVAILABLE_AUTOFILL_PAYMENT_METHODS,
super(DELEGATE, WEB_CONTENTS, VISIBLE, SELECTED_SHIPPING_ADDRESS,
SELECTED_PAYMENT_INSTRUMENT, SELECTED_CONTACT_DETAILS, LOGIN_SECTION_TITLE,
SELECTED_LOGIN, TERMS_STATUS, REQUEST_NAME, REQUEST_EMAIL, REQUEST_PHONE,
REQUEST_SHIPPING_ADDRESS, REQUEST_PAYMENT, ACCEPT_TERMS_AND_CONDITIONS_TEXT,
SHOW_TERMS_AS_CHECKBOX, REQUEST_LOGIN_CHOICE, AVAILABLE_BILLING_ADDRESSES,
AVAILABLE_CONTACTS, AVAILABLE_SHIPPING_ADDRESSES, AVAILABLE_PAYMENT_INSTRUMENTS,
SUPPORTED_BASIC_CARD_NETWORKS, AVAILABLE_LOGINS, EXPANDED_SECTION,
REQUIRE_BILLING_POSTAL_CODE, BILLING_POSTAL_CODE_MISSING_TEXT,
CREDIT_CARD_EXPIRED_TEXT, REQUEST_DATE_RANGE, DATE_RANGE_START,
......@@ -185,8 +175,12 @@ public class AssistantCollectUserDataModel extends PropertyModel {
set(REQUIRE_BILLING_POSTAL_CODE, false);
set(DATE_RANGE_START_LABEL, "");
set(DATE_RANGE_END_LABEL, "");
set(PREPENDED_SECTIONS, new ArrayList<>());
set(APPENDED_SECTIONS, new ArrayList<>());
set(PREPENDED_SECTIONS, Collections.emptyList());
set(APPENDED_SECTIONS, Collections.emptyList());
set(AVAILABLE_PAYMENT_INSTRUMENTS, Collections.emptyList());
set(AVAILABLE_CONTACTS, Collections.emptyList());
set(AVAILABLE_SHIPPING_ADDRESSES, Collections.emptyList());
set(AVAILABLE_BILLING_ADDRESSES, Collections.emptyList());
}
@CalledByNative
......@@ -275,23 +269,20 @@ public class AssistantCollectUserDataModel extends PropertyModel {
}
@CalledByNative
private void setContactDetails(@Nullable PersonalDataManager.AutofillProfile contact) {
set(CONTACT_DETAILS, contact);
private void setSelectedContactDetails(@Nullable AutofillContact contact) {
set(SELECTED_CONTACT_DETAILS, contact);
}
@CalledByNative
private void setShippingAddress(@Nullable PersonalDataManager.AutofillProfile shippingAddress) {
set(SHIPPING_ADDRESS, shippingAddress);
private void setSelectedShippingAddress(@Nullable AutofillAddress shippingAddress) {
set(SELECTED_SHIPPING_ADDRESS, shippingAddress);
}
@CalledByNative
private void setPaymentMethod(@Nullable PersonalDataManager.CreditCard card,
@Nullable PersonalDataManager.AutofillProfile billingAddress) {
if (card == null) {
set(PAYMENT_METHOD, null);
} else {
set(PAYMENT_METHOD, new PaymentTuple(card, billingAddress));
}
private void setSelectedPaymentInstrument(@Nullable PersonalDataManager.CreditCard card,
@Nullable PersonalDataManager.AutofillProfile billingProfile) {
set(SELECTED_PAYMENT_INSTRUMENT,
createAutofillPaymentInstrument(get(WEB_CONTENTS), card, billingProfile));
}
/** Creates an empty list of login options. */
......@@ -406,39 +397,109 @@ public class AssistantCollectUserDataModel extends PropertyModel {
}
@CalledByNative
private static List<PersonalDataManager.AutofillProfile> createAutofillProfileList() {
private static List<AutofillContact> createAutofillContactList() {
return new ArrayList<>();
}
@CalledByNative
private static void addAutofillProfile(List<PersonalDataManager.AutofillProfile> profiles,
PersonalDataManager.AutofillProfile profile) {
profiles.add(profile);
private static void addAutofillContact(
List<AutofillContact> contacts, AutofillContact contact) {
contacts.add(contact);
}
@VisibleForTesting
@CalledByNative
@Nullable
public static AutofillContact createAutofillContact(Context context,
@Nullable PersonalDataManager.AutofillProfile profile, boolean requestName,
boolean requestPhone, boolean requestEmail) {
if (profile == null || !(requestName || requestPhone || requestEmail)) {
return null;
}
ContactEditor editor =
new ContactEditor(requestName, requestPhone, requestEmail, /* saveToDisk= */ false);
String name = profile.getFullName();
String phone = profile.getPhoneNumber();
String email = profile.getEmailAddress();
return new AutofillContact(context, profile, name, phone, email,
editor.checkContactCompletionStatus(name, phone, email), requestName, requestPhone,
requestEmail);
}
@CalledByNative
private void setAutofillProfiles(List<PersonalDataManager.AutofillProfile> profiles) {
set(AVAILABLE_PROFILES, profiles);
private void setAvailableContacts(List<AutofillContact> contacts) {
set(AVAILABLE_CONTACTS, contacts);
}
@CalledByNative
private static List<AssistantCollectUserDataModel.PaymentTuple>
createAutofillPaymentMethodList() {
private static List<AutofillAddress> createAutofillAddressList() {
return new ArrayList<>();
}
@CalledByNative
private static void addAutofillPaymentMethod(
List<AssistantCollectUserDataModel.PaymentTuple> paymentTuples,
PersonalDataManager.CreditCard card,
@Nullable PersonalDataManager.AutofillProfile billingAddress) {
paymentTuples.add(new PaymentTuple(card, billingAddress));
private static void addAutofillAddress(
List<AutofillAddress> addresses, AutofillAddress address) {
addresses.add(address);
}
@VisibleForTesting
@CalledByNative
@Nullable
public static AutofillAddress createAutofillAddress(
Context context, @Nullable PersonalDataManager.AutofillProfile profile) {
if (profile == null) {
return null;
}
return new AutofillAddress(context, profile);
}
@CalledByNative
private void setAvailableShippingAddresses(List<AutofillAddress> addresses) {
set(AVAILABLE_SHIPPING_ADDRESSES, addresses);
}
@CalledByNative
private void setAvailableBillingAddresses(List<AutofillAddress> addresses) {
set(AVAILABLE_BILLING_ADDRESSES, addresses);
}
@CalledByNative
private static List<AutofillPaymentInstrument> createAutofillPaymentInstrumentList() {
return new ArrayList<>();
}
// TODO(b/144005336): Make this method static.
@CalledByNative
private void addAutofillPaymentInstrument(List<AutofillPaymentInstrument> paymentInstruments,
@Nullable PersonalDataManager.CreditCard card,
@Nullable PersonalDataManager.AutofillProfile billingProfile) {
AutofillPaymentInstrument paymentInstrument =
createAutofillPaymentInstrument(get(WEB_CONTENTS), card, billingProfile);
if (paymentInstrument != null) {
paymentInstruments.add(paymentInstrument);
}
}
// TODO(b/144005336): Call from native instead.
@VisibleForTesting
@Nullable
public static AutofillPaymentInstrument createAutofillPaymentInstrument(
@Nullable WebContents webContents, @Nullable PersonalDataManager.CreditCard card,
@Nullable PersonalDataManager.AutofillProfile billingProfile) {
if (webContents == null) {
return null;
}
if (card == null) {
return null;
}
return new AutofillPaymentInstrument(webContents, card, billingProfile,
MethodStrings.BASIC_CARD, /* matchesMerchantCardTypeExactly= */ true);
}
@CalledByNative
private void setAutofillPaymentMethods(
List<AssistantCollectUserDataModel.PaymentTuple> paymentTuples) {
set(AVAILABLE_AUTOFILL_PAYMENT_METHODS, paymentTuples);
private void setAvailablePaymentInstruments(
List<AutofillPaymentInstrument> paymentInstruments) {
set(AVAILABLE_PAYMENT_INSTRUMENTS, paymentInstruments);
}
@CalledByNative
......
......@@ -14,12 +14,9 @@ import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import org.chromium.chrome.autofill_assistant.R;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.payments.AutofillContact;
import org.chromium.chrome.browser.payments.ContactEditor;
import org.chromium.chrome.browser.payments.ui.ContactDetailsSection;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -140,39 +137,21 @@ public class AssistantContactDetailsSection
/**
* The Chrome profiles have changed externally. This will rebuild the UI with the new/changed
* set of profiles, while keeping the selected item if possible.
* set of contacts derived from the profiles, while keeping the selected item if possible.
*/
void onProfilesChanged(List<AutofillProfile> profiles, boolean requestPayerEmail,
boolean requestPayerName, boolean requestPayerPhone) {
void onContactsChanged(List<AutofillContact> contacts) {
if (mIgnoreProfileChangeNotifications) {
return;
}
if (!requestPayerEmail && !requestPayerName && !requestPayerPhone) {
return;
}
// Note: we create a temporary editor (necessary for converting profiles to contacts)
// instead of using mEditor, which may be null.
ContactEditor tempEditor =
new ContactEditor(requestPayerName, requestPayerPhone, requestPayerEmail, false);
// Convert profiles into a list of |AutofillContact|.
int selectedContactIndex = -1;
ContactDetailsSection sectionInformation =
new ContactDetailsSection(mContext, profiles, tempEditor, null);
List<AutofillContact> contacts = new ArrayList<>();
for (int i = 0; i < sectionInformation.getSize(); i++) {
AutofillContact contact = (AutofillContact) sectionInformation.getItem(i);
if (contact == null) {
continue;
}
contacts.add(contact);
if (mSelectedOption != null && areEqual(contact, mSelectedOption)) {
selectedContactIndex = i;
if (mSelectedOption != null) {
for (int i = 0; i < contacts.size(); i++) {
if (areEqual(contacts.get(i), mSelectedOption)) {
selectedContactIndex = i;
break;
}
}
}
// Replace current set of items, keep selection if possible.
setItems(contacts, selectedContactIndex);
}
......
......@@ -57,7 +57,7 @@ public class AssistantPaymentMethodSection
String guid = method.getCard().getBillingAddressId();
PersonalDataManager.AutofillProfile profile = personalDataManager.getProfile(guid);
if (profile != null) {
addAutocompleteInformationToEditor(profile);
addAutocompleteInformationToEditor(new AutofillAddress(mContext, profile));
}
}
}
......@@ -167,10 +167,10 @@ public class AssistantPaymentMethodSection
return TextUtils.equals(profileA.getGUID(), profileB.getGUID());
}
void onProfilesChanged(List<PersonalDataManager.AutofillProfile> profiles) {
void onAddressesChanged(List<AutofillAddress> addresses) {
// TODO(crbug.com/806868): replace suggested billing addresses (remove if necessary).
for (PersonalDataManager.AutofillProfile profile : profiles) {
addAutocompleteInformationToEditor(profile);
for (AutofillAddress address : addresses) {
addAutocompleteInformationToEditor(address);
}
}
......@@ -209,12 +209,12 @@ public class AssistantPaymentMethodSection
mCreditCardExpiredText = text;
}
private void addAutocompleteInformationToEditor(PersonalDataManager.AutofillProfile profile) {
private void addAutocompleteInformationToEditor(AutofillAddress address) {
// The check for non-null label is necessary to prevent crash in editor when opening.
if (mEditor == null || profile.getLabel() == null) {
if (mEditor == null || address.getProfile().getLabel() == null) {
return;
}
mEditor.updateBillingAddressIfComplete(new AutofillAddress(mContext, profile));
mEditor.updateBillingAddressIfComplete(address);
}
private void setErrorMessage(TextView errorMessageView, AutofillPaymentInstrument method) {
......
......@@ -18,7 +18,6 @@ import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.payments.AddressEditor;
import org.chromium.chrome.browser.payments.AutofillAddress;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -125,21 +124,23 @@ public class AssistantShippingAddressSection
return TextUtils.equals(optionA.getProfile().getGUID(), optionB.getProfile().getGUID());
}
void onProfilesChanged(List<PersonalDataManager.AutofillProfile> profiles) {
/**
* The Chrome profiles have changed externally. This will rebuild the UI with the new/changed
* set of addresses derived from the profiles, while keeping the selected item if possible.
*/
void onAddressesChanged(List<AutofillAddress> addresses) {
if (mIgnoreProfileChangeNotifications) {
return;
}
int selectedAddressIndex = -1;
List<AutofillAddress> addresses = new ArrayList<>();
for (int i = 0; i < profiles.size(); i++) {
AutofillAddress autofillAddress = new AutofillAddress(mContext, profiles.get(i));
if (mSelectedOption != null && areEqual(mSelectedOption, autofillAddress)) {
selectedAddressIndex = i;
if (mSelectedOption != null) {
for (int i = 0; i < addresses.size(); i++) {
if (areEqual(addresses.get(i), mSelectedOption)) {
selectedAddressIndex = i;
break;
}
}
addresses.add(autofillAddress);
}
// Replace current set of items, keep selection if possible.
setItems(addresses, selectedAddressIndex);
}
......
......@@ -64,6 +64,9 @@ import org.chromium.chrome.browser.autofill_assistant.user_data.additional_secti
import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputSection.TextInputFactory;
import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputType;
import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
import org.chromium.chrome.browser.payments.AutofillAddress;
import org.chromium.chrome.browser.payments.AutofillContact;
import org.chromium.chrome.browser.payments.AutofillPaymentInstrument;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
......@@ -131,17 +134,18 @@ public class AutofillAssistantCollectUserDataUiTest {
/* Test initial model state. */
assertThat(model.get(AssistantCollectUserDataModel.VISIBLE), is(false));
assertThat(model.get(AssistantCollectUserDataModel.AVAILABLE_PROFILES), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS),
nullValue());
assertThat(model.get(AssistantCollectUserDataModel.AVAILABLE_CONTACTS), empty());
assertThat(model.get(AssistantCollectUserDataModel.AVAILABLE_SHIPPING_ADDRESSES), empty());
assertThat(model.get(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS), empty());
assertThat(model.get(AssistantCollectUserDataModel.SUPPORTED_BASIC_CARD_NETWORKS),
nullValue());
assertThat(model.get(AssistantCollectUserDataModel.EXPANDED_SECTION), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.DELEGATE), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.WEB_CONTENTS), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.SHIPPING_ADDRESS), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.PAYMENT_METHOD), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.CONTACT_DETAILS), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.SELECTED_SHIPPING_ADDRESS), nullValue());
assertThat(
model.get(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS), nullValue());
assertThat(model.get(AssistantCollectUserDataModel.TERMS_STATUS),
is(AssistantTermsAndConditionsState.NOT_SELECTED));
assertThat(model.get(AssistantCollectUserDataModel.SELECTED_LOGIN), nullValue());
......@@ -378,8 +382,8 @@ public class AutofillAssistantCollectUserDataUiTest {
model.set(AssistantCollectUserDataModel.WEB_CONTENTS, mTestRule.getWebContents());
model.set(AssistantCollectUserDataModel.REQUEST_NAME, true);
model.set(AssistantCollectUserDataModel.REQUEST_EMAIL, true);
model.set(AssistantCollectUserDataModel.AVAILABLE_PROFILES, Collections.emptyList());
model.set(AssistantCollectUserDataModel.CONTACT_DETAILS, null);
model.set(AssistantCollectUserDataModel.AVAILABLE_CONTACTS, Collections.emptyList());
model.set(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS, null);
model.set(AssistantCollectUserDataModel.VISIBLE, true);
});
......@@ -390,12 +394,14 @@ public class AutofillAssistantCollectUserDataUiTest {
assertThat(viewHolder.mContactList.getItemCount(), is(0));
// Add profile to the list and send the updated model.
PersonalDataManager.AutofillProfile profile =
mHelper.createDummyProfile("John Doe", "john@gmail.com");
TestThreadUtils.runOnUiThreadBlocking(() -> {
model.set(AssistantCollectUserDataModel.AVAILABLE_PROFILES,
Collections.singletonList(profile));
model.set(AssistantCollectUserDataModel.CONTACT_DETAILS, profile);
AutofillContact contact = AssistantCollectUserDataModel.createAutofillContact(
mTestRule.getActivity(),
mHelper.createDummyProfile("John Doe", "john@gmail.com"),
/* requestName= */ true, /* requestPhone= */ true, /* requestEmail= */ false);
model.set(AssistantCollectUserDataModel.AVAILABLE_CONTACTS,
Collections.singletonList(contact));
model.set(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS, contact);
});
// Contact details section should now contain and have pre-selected the new contact.
......@@ -409,8 +415,8 @@ public class AutofillAssistantCollectUserDataUiTest {
// Remove profile from the list and send the updated model. Section should be empty again.
TestThreadUtils.runOnUiThreadBlocking(() -> {
model.set(AssistantCollectUserDataModel.AVAILABLE_PROFILES, Collections.emptyList());
model.set(AssistantCollectUserDataModel.CONTACT_DETAILS, null);
model.set(AssistantCollectUserDataModel.AVAILABLE_CONTACTS, Collections.emptyList());
model.set(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS, null);
});
onView(allOf(withId(R.id.section_title_add_button),
......@@ -443,9 +449,9 @@ public class AutofillAssistantCollectUserDataUiTest {
model.set(AssistantCollectUserDataModel.WEB_CONTENTS, mTestRule.getWebContents());
model.set(AssistantCollectUserDataModel.REQUEST_PAYMENT, true);
model.set(AssistantCollectUserDataModel.VISIBLE, true);
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.emptyList());
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, null);
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT, null);
});
// Payment method section should be empty and show the 'add' button in the title.
......@@ -459,13 +465,14 @@ public class AutofillAssistantCollectUserDataUiTest {
mHelper.createDummyProfile("Jill Doe", "jill@gmail.com");
String billingAddressId = mHelper.setProfile(billingAddress);
PersonalDataManager.CreditCard creditCard = mHelper.createDummyCreditCard(billingAddressId);
AssistantCollectUserDataModel.PaymentTuple paymentTuple =
new AssistantCollectUserDataModel.PaymentTuple(creditCard, billingAddress);
TestThreadUtils.runOnUiThreadBlocking(() -> {
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
Collections.singletonList(paymentTuple));
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, paymentTuple);
AutofillPaymentInstrument paymentInstrument =
AssistantCollectUserDataModel.createAutofillPaymentInstrument(
mTestRule.getWebContents(), creditCard, billingAddress);
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.singletonList(paymentInstrument));
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT, paymentInstrument);
});
// Payment method section contains the new credit card, which should be pre-selected.
......@@ -479,9 +486,9 @@ public class AutofillAssistantCollectUserDataUiTest {
// Remove credit card from the list. Section should be empty again.
TestThreadUtils.runOnUiThreadBlocking(() -> {
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.emptyList());
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, null);
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT, null);
});
onView(allOf(withId(R.id.section_title_add_button),
isDescendantOfA(is(viewHolder.mPaymentSection))))
......@@ -508,17 +515,18 @@ public class AutofillAssistantCollectUserDataUiTest {
mHelper.createDummyProfile("Jill Doe", "jill@gmail.com");
String billingAddressId = mHelper.setProfile(billingAddress);
PersonalDataManager.CreditCard creditCard = mHelper.createDummyCreditCard(billingAddressId);
AssistantCollectUserDataModel.PaymentTuple paymentTuple =
new AssistantCollectUserDataModel.PaymentTuple(creditCard, billingAddress);
TestThreadUtils.runOnUiThreadBlocking(() -> {
// WEB_CONTENTS are necessary for the creation of the editors.
model.set(AssistantCollectUserDataModel.WEB_CONTENTS, mTestRule.getWebContents());
model.set(AssistantCollectUserDataModel.REQUEST_PAYMENT, true);
model.set(AssistantCollectUserDataModel.VISIBLE, true);
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
Collections.singletonList(paymentTuple));
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, paymentTuple);
AutofillPaymentInstrument paymentInstrument =
AssistantCollectUserDataModel.createAutofillPaymentInstrument(
mTestRule.getWebContents(), creditCard, billingAddress);
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.singletonList(paymentInstrument));
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT, paymentInstrument);
});
// Payment method section contains the new credit card, which should be pre-selected.
......@@ -569,8 +577,6 @@ public class AutofillAssistantCollectUserDataUiTest {
new PersonalDataManager.CreditCard("", "https://example.com", true, true, "Jon Doe",
"4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
CardType.UNKNOWN, /* billingAddressId= */ "GUID", /* serverId= */ "");
AssistantCollectUserDataModel.PaymentTuple paymentTuple =
new AssistantCollectUserDataModel.PaymentTuple(creditCard, profile);
AssistantCollectUserDataModel model = new AssistantCollectUserDataModel();
AssistantCollectUserDataCoordinator coordinator = createCollectUserDataCoordinator(model);
......@@ -590,13 +596,23 @@ public class AutofillAssistantCollectUserDataUiTest {
model.set(AssistantCollectUserDataModel.REQUEST_EMAIL, true);
model.set(AssistantCollectUserDataModel.REQUEST_PAYMENT, true);
model.set(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS, true);
model.set(AssistantCollectUserDataModel.AVAILABLE_PROFILES,
Collections.singletonList(profile));
model.set(AssistantCollectUserDataModel.CONTACT_DETAILS, profile);
model.set(AssistantCollectUserDataModel.SHIPPING_ADDRESS, profile);
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
Collections.singletonList(paymentTuple));
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, paymentTuple);
AutofillContact contact = AssistantCollectUserDataModel.createAutofillContact(
mTestRule.getActivity(), profile, /* requestName= */ true,
/* requestPhone= */ true, /* requestEmail= */ true);
model.set(AssistantCollectUserDataModel.AVAILABLE_CONTACTS,
Collections.singletonList(contact));
model.set(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS, contact);
AutofillAddress address = AssistantCollectUserDataModel.createAutofillAddress(
mTestRule.getActivity(), profile);
model.set(AssistantCollectUserDataModel.AVAILABLE_SHIPPING_ADDRESSES,
Collections.singletonList(address));
model.set(AssistantCollectUserDataModel.SELECTED_SHIPPING_ADDRESS, address);
AutofillPaymentInstrument paymentInstrument =
AssistantCollectUserDataModel.createAutofillPaymentInstrument(
mTestRule.getWebContents(), creditCard, profile);
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.singletonList(paymentInstrument));
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT, paymentInstrument);
model.set(AssistantCollectUserDataModel.VISIBLE, true);
model.set(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE, true);
model.set(AssistantCollectUserDataModel.AVAILABLE_LOGINS,
......@@ -820,9 +836,6 @@ public class AutofillAssistantCollectUserDataUiTest {
PersonalDataManager.CreditCard creditCard = mHelper.createDummyCreditCard(profileId);
creditCard.setYear("2019");
AssistantCollectUserDataModel.PaymentTuple expiredPaymentTuple =
new AssistantCollectUserDataModel.PaymentTuple(creditCard, profile);
AssistantCollectUserDataModel model = new AssistantCollectUserDataModel();
AssistantCollectUserDataCoordinator coordinator = createCollectUserDataCoordinator(model);
AutofillAssistantCollectUserDataTestHelper
......@@ -835,9 +848,13 @@ public class AutofillAssistantCollectUserDataUiTest {
model.set(AssistantCollectUserDataModel.REQUEST_PAYMENT, true);
model.set(AssistantCollectUserDataModel.CREDIT_CARD_EXPIRED_TEXT, "Card is expired");
model.set(AssistantCollectUserDataModel.VISIBLE, true);
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
Collections.singletonList(expiredPaymentTuple));
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, expiredPaymentTuple);
AutofillPaymentInstrument expiredPaymentInstrument =
AssistantCollectUserDataModel.createAutofillPaymentInstrument(
mTestRule.getWebContents(), creditCard, profile);
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.singletonList(expiredPaymentInstrument));
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT,
expiredPaymentInstrument);
});
// check that the card is not accepted (i.e. an error message is shown).
......@@ -846,12 +863,15 @@ public class AutofillAssistantCollectUserDataUiTest {
.check(matches(withText("Card is expired")));
creditCard.setYear("2050");
AssistantCollectUserDataModel.PaymentTuple validPaymentTuple =
new AssistantCollectUserDataModel.PaymentTuple(creditCard, profile);
TestThreadUtils.runOnUiThreadBlocking(() -> {
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
Collections.singletonList(validPaymentTuple));
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, validPaymentTuple);
AutofillPaymentInstrument validPaymentInstrument =
AssistantCollectUserDataModel.createAutofillPaymentInstrument(
mTestRule.getWebContents(), creditCard, profile);
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.singletonList(validPaymentInstrument));
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT,
validPaymentInstrument);
});
// check that the card is now accepted.
......@@ -890,8 +910,6 @@ public class AutofillAssistantCollectUserDataUiTest {
AutofillAssistantCollectUserDataTestHelper
.ViewHolder viewHolder = TestThreadUtils.runOnUiThreadBlocking(
() -> new AutofillAssistantCollectUserDataTestHelper.ViewHolder(coordinator));
AssistantCollectUserDataModel.PaymentTuple paymentTuple =
new AssistantCollectUserDataModel.PaymentTuple(creditCard, profile);
TestThreadUtils.runOnUiThreadBlocking(() -> {
// WEB_CONTENTS are necessary for the creation of AutofillPaymentInstrument.
......@@ -902,9 +920,12 @@ public class AutofillAssistantCollectUserDataUiTest {
model.set(AssistantCollectUserDataModel.BILLING_POSTAL_CODE_MISSING_TEXT,
"Billing postcode missing");
model.set(AssistantCollectUserDataModel.REQUEST_PAYMENT, true);
model.set(AssistantCollectUserDataModel.AVAILABLE_AUTOFILL_PAYMENT_METHODS,
Collections.singletonList(paymentTuple));
model.set(AssistantCollectUserDataModel.PAYMENT_METHOD, paymentTuple);
AutofillPaymentInstrument paymentInstrument =
AssistantCollectUserDataModel.createAutofillPaymentInstrument(
mTestRule.getWebContents(), creditCard, profile);
model.set(AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS,
Collections.singletonList(paymentInstrument));
model.set(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT, paymentInstrument);
model.set(AssistantCollectUserDataModel.VISIBLE, true);
});
......
......@@ -1031,6 +1031,9 @@ void UiControllerAndroid::OnUserDataChanged(
return;
}
auto jcontext =
Java_AutofillAssistantUiController_getContext(env, java_object_);
if (field_change == UserData::FieldChange::ALL ||
field_change == UserData::FieldChange::TERMS_AND_CONDITIONS) {
Java_AssistantCollectUserDataModel_setTermsStatus(
......@@ -1039,65 +1042,119 @@ void UiControllerAndroid::OnUserDataChanged(
if (field_change == UserData::FieldChange::ALL ||
field_change == UserData::FieldChange::AVAILABLE_PROFILES) {
auto sorted_profile_indices = SortByCompleteness(*collect_user_data_options,
state->available_profiles);
auto jlist =
Java_AssistantCollectUserDataModel_createAutofillProfileList(env);
for (int index : sorted_profile_indices) {
Java_AssistantCollectUserDataModel_addAutofillProfile(
env, jlist,
// Contact profiles.
auto jcontactlist =
Java_AssistantCollectUserDataModel_createAutofillContactList(env);
auto contact_indices = SortContactsByCompleteness(
*collect_user_data_options, state->available_profiles);
for (int index : contact_indices) {
auto jcontact = Java_AssistantCollectUserDataModel_createAutofillContact(
env, jcontext,
autofill::PersonalDataManagerAndroid::CreateJavaProfileFromNative(
env, *state->available_profiles[index]));
env, *state->available_profiles[index]),
collect_user_data_options->request_payer_name,
collect_user_data_options->request_payer_phone,
collect_user_data_options->request_payer_email);
if (jcontact) {
Java_AssistantCollectUserDataModel_addAutofillContact(env, jcontactlist,
jcontact);
}
}
Java_AssistantCollectUserDataModel_setAutofillProfiles(env, jmodel, jlist);
Java_AssistantCollectUserDataModel_setAvailableContacts(env, jmodel,
jcontactlist);
// Ignore changes to FieldChange::CONTACT_PROFILE, this is already coming
// from the view.
autofill::AutofillProfile* contact_profile = state->contact_profile.get();
Java_AssistantCollectUserDataModel_setContactDetails(
Java_AssistantCollectUserDataModel_setSelectedContactDetails(
env, jmodel,
contact_profile == nullptr
? nullptr
: autofill::PersonalDataManagerAndroid::CreateJavaProfileFromNative(
env, *contact_profile));
: Java_AssistantCollectUserDataModel_createAutofillContact(
env, jcontext,
autofill::PersonalDataManagerAndroid::
CreateJavaProfileFromNative(env, *contact_profile),
collect_user_data_options->request_payer_name,
collect_user_data_options->request_payer_phone,
collect_user_data_options->request_payer_email));
// Billing addresses profiles.
auto jbillinglist =
Java_AssistantCollectUserDataModel_createAutofillAddressList(env);
for (const auto& profile : state->available_profiles) {
auto jaddress = Java_AssistantCollectUserDataModel_createAutofillAddress(
env, jcontext,
autofill::PersonalDataManagerAndroid::CreateJavaProfileFromNative(
env, *profile));
if (jaddress) {
Java_AssistantCollectUserDataModel_addAutofillAddress(env, jbillinglist,
jaddress);
}
}
Java_AssistantCollectUserDataModel_setAvailableBillingAddresses(
env, jmodel, jbillinglist);
// Address profiles.
auto jshippinglist =
Java_AssistantCollectUserDataModel_createAutofillAddressList(env);
auto address_indices = SortAddressesByCompleteness(
*collect_user_data_options, state->available_profiles);
for (int index : address_indices) {
auto jaddress = Java_AssistantCollectUserDataModel_createAutofillAddress(
env, jcontext,
autofill::PersonalDataManagerAndroid::CreateJavaProfileFromNative(
env, *state->available_profiles[index]));
if (jaddress) {
Java_AssistantCollectUserDataModel_addAutofillAddress(
env, jshippinglist, jaddress);
}
}
Java_AssistantCollectUserDataModel_setAvailableShippingAddresses(
env, jmodel, jshippinglist);
// Ignore changes to FieldChange::SHIPPING_ADDRESS, this is already coming
// from the view.
autofill::AutofillProfile* shipping_address = state->shipping_address.get();
Java_AssistantCollectUserDataModel_setShippingAddress(
Java_AssistantCollectUserDataModel_setSelectedShippingAddress(
env, jmodel,
shipping_address == nullptr
? nullptr
: autofill::PersonalDataManagerAndroid::CreateJavaProfileFromNative(
env, *shipping_address));
: Java_AssistantCollectUserDataModel_createAutofillAddress(
env, jcontext,
autofill::PersonalDataManagerAndroid::
CreateJavaProfileFromNative(env, *shipping_address)));
}
if (field_change == UserData::FieldChange::ALL ||
field_change == UserData::FieldChange::AVAILABLE_PAYMENT_INSTRUMENTS) {
auto sorted_payment_instrument_indices = SortByCompleteness(
*collect_user_data_options, state->available_payment_instruments);
auto jlist =
Java_AssistantCollectUserDataModel_createAutofillPaymentMethodList(env);
Java_AssistantCollectUserDataModel_createAutofillPaymentInstrumentList(
env);
auto sorted_payment_instrument_indices =
SortPaymentInstrumentsByCompleteness(
*collect_user_data_options, state->available_payment_instruments);
for (int index : sorted_payment_instrument_indices) {
const auto& instrument = state->available_payment_instruments[index];
Java_AssistantCollectUserDataModel_addAutofillPaymentMethod(
env, jlist,
autofill::PersonalDataManagerAndroid::CreateJavaCreditCardFromNative(
env, *(instrument->card)),
Java_AssistantCollectUserDataModel_addAutofillPaymentInstrument(
env, jmodel, jlist,
instrument->card == nullptr
? nullptr
: autofill::PersonalDataManagerAndroid::
CreateJavaCreditCardFromNative(env, *(instrument->card)),
instrument->billing_address == nullptr
? nullptr
: autofill::PersonalDataManagerAndroid::
CreateJavaProfileFromNative(
env, *(instrument->billing_address)));
}
Java_AssistantCollectUserDataModel_setAutofillPaymentMethods(env, jmodel,
jlist);
Java_AssistantCollectUserDataModel_setAvailablePaymentInstruments(
env, jmodel, jlist);
// Ignore changes to FieldChange::CARD, this is already coming from the
// view.
autofill::CreditCard* card = state->card.get();
autofill::AutofillProfile* billing_address = state->billing_address.get();
Java_AssistantCollectUserDataModel_setPaymentMethod(
Java_AssistantCollectUserDataModel_setSelectedPaymentInstrument(
env, jmodel,
card == nullptr ? nullptr
: autofill::PersonalDataManagerAndroid::
......
......@@ -844,8 +844,8 @@ void CollectUserDataAction::UpdatePersonalDataManagerProfiles(
(collect_user_data_options_->request_payer_name ||
collect_user_data_options_->request_payer_phone ||
collect_user_data_options_->request_payer_email)) {
int default_selection = GetDefaultProfile(*collect_user_data_options_,
user_data->available_profiles);
int default_selection = GetDefaultContactProfile(
*collect_user_data_options_, user_data->available_profiles);
if (default_selection != -1) {
user_data->contact_profile = std::make_unique<autofill::AutofillProfile>(
*(user_data->available_profiles[default_selection]));
......@@ -857,8 +857,8 @@ void CollectUserDataAction::UpdatePersonalDataManagerProfiles(
}
if (user_data->shipping_address == nullptr &&
collect_user_data_options_->request_shipping) {
int default_selection = GetDefaultProfile(*collect_user_data_options_,
user_data->available_profiles);
int default_selection = GetDefaultAddressProfile(
*collect_user_data_options_, user_data->available_profiles);
if (default_selection != -1) {
user_data->shipping_address = std::make_unique<autofill::AutofillProfile>(
*(user_data->available_profiles[default_selection]));
......
......@@ -8,6 +8,9 @@
#include "base/i18n/case_conversion.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/geo/address_i18n.h"
#include "third_party/libaddressinput/chromium/addressinput_util.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
namespace autofill_assistant {
namespace {
......@@ -20,8 +23,8 @@ base::string16 GetProfileFullName(const autofill::AutofillProfile& profile) {
profile.GetRawInfo(autofill::NAME_LAST));
}
int CountCompleteFields(const CollectUserDataOptions& options,
const autofill::AutofillProfile& profile) {
int CountCompleteContactFields(const CollectUserDataOptions& options,
const autofill::AutofillProfile& profile) {
int completed_fields = 0;
if (options.request_payer_name && !GetProfileFullName(profile).empty()) {
++completed_fields;
......@@ -44,11 +47,11 @@ int CountCompleteFields(const CollectUserDataOptions& options,
// Helper function that compares instances of AutofillProfile by completeness
// in regards to the current options. Full profiles should be ordered before
// empty ones and fall back to compare the profile's name in case of equality.
bool CompletenessCompare(const CollectUserDataOptions& options,
const autofill::AutofillProfile& a,
const autofill::AutofillProfile& b) {
int complete_fields_a = CountCompleteFields(options, a);
int complete_fields_b = CountCompleteFields(options, b);
bool CompletenessCompareContacts(const CollectUserDataOptions& options,
const autofill::AutofillProfile& a,
const autofill::AutofillProfile& b) {
int complete_fields_a = CountCompleteContactFields(options, a);
int complete_fields_b = CountCompleteContactFields(options, b);
if (complete_fields_a == complete_fields_b) {
return base::i18n::ToLower(GetProfileFullName(a))
.compare(base::i18n::ToLower(GetProfileFullName(b))) < 0;
......@@ -56,8 +59,35 @@ bool CompletenessCompare(const CollectUserDataOptions& options,
return complete_fields_a > complete_fields_b;
}
int CountCompleteFields(const CollectUserDataOptions& options,
const PaymentInstrument& instrument) {
int GetAddressCompletenessRating(const CollectUserDataOptions& options,
const autofill::AutofillProfile& profile) {
auto address_data =
autofill::i18n::CreateAddressDataFromAutofillProfile(profile, "en-US");
std::multimap<i18n::addressinput::AddressField,
i18n::addressinput::AddressProblem>
problems;
autofill::addressinput::ValidateRequiredFields(
*address_data, /* filter= */ nullptr, &problems);
return -problems.size();
}
// Helper function that compares instances of AutofillProfile by completeness
// in regards to the current options. Full profiles should be ordered before
// empty ones and fall back to compare the profile's name in case of equality.
bool CompletenessCompareAddresses(const CollectUserDataOptions& options,
const autofill::AutofillProfile& a,
const autofill::AutofillProfile& b) {
int complete_fields_a = GetAddressCompletenessRating(options, a);
int complete_fields_b = GetAddressCompletenessRating(options, b);
if (complete_fields_a == complete_fields_b) {
return base::i18n::ToLower(GetProfileFullName(a))
.compare(base::i18n::ToLower(GetProfileFullName(b))) < 0;
}
return complete_fields_a > complete_fields_b;
}
int CountCompletePaymentInstrumentFields(const CollectUserDataOptions& options,
const PaymentInstrument& instrument) {
int complete_fields = 0;
if (!instrument.card->GetRawInfo(autofill::CREDIT_CARD_NAME_FULL).empty()) {
++complete_fields;
......@@ -88,11 +118,12 @@ int CountCompleteFields(const CollectUserDataOptions& options,
// in regards to the current options. Full payment instruments should be
// ordered before empty ones and fall back to compare the full name on the
// credit card in case of equality.
bool CompletenessCompare(const CollectUserDataOptions& options,
const PaymentInstrument& a,
const PaymentInstrument& b) {
int complete_fields_a = CountCompleteFields(options, a);
int complete_fields_b = CountCompleteFields(options, b);
bool CompletenessComparePaymentInstruments(
const CollectUserDataOptions& options,
const PaymentInstrument& a,
const PaymentInstrument& b) {
int complete_fields_a = CountCompletePaymentInstrumentFields(options, a);
int complete_fields_b = CountCompletePaymentInstrumentFields(options, b);
if (complete_fields_a == complete_fields_b) {
return base::i18n::ToLower(
a.card->GetRawInfo(autofill::CREDIT_CARD_NAME_FULL))
......@@ -104,26 +135,27 @@ bool CompletenessCompare(const CollectUserDataOptions& options,
} // namespace
std::vector<int> SortByCompleteness(
std::vector<int> SortContactsByCompleteness(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles) {
std::vector<int> profile_indices(profiles.size());
std::iota(std::begin(profile_indices), std::end(profile_indices), 0);
std::sort(profile_indices.begin(), profile_indices.end(),
[&collect_user_data_options, &profiles](int i, int j) {
return CompletenessCompare(collect_user_data_options,
*profiles[i], *profiles[j]);
return CompletenessCompareContacts(collect_user_data_options,
*profiles[i], *profiles[j]);
});
return profile_indices;
}
int GetDefaultProfile(
int GetDefaultContactProfile(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles) {
if (profiles.empty()) {
return -1;
}
auto sorted_indices = SortByCompleteness(collect_user_data_options, profiles);
auto sorted_indices =
SortContactsByCompleteness(collect_user_data_options, profiles);
if (!collect_user_data_options.default_email.empty()) {
for (int index : sorted_indices) {
if (base::UTF16ToUTF8(
......@@ -136,7 +168,31 @@ int GetDefaultProfile(
return sorted_indices[0];
}
std::vector<int> SortByCompleteness(
std::vector<int> SortAddressesByCompleteness(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles) {
std::vector<int> profile_indices(profiles.size());
std::iota(std::begin(profile_indices), std::end(profile_indices), 0);
std::sort(profile_indices.begin(), profile_indices.end(),
[&collect_user_data_options, &profiles](int i, int j) {
return CompletenessCompareAddresses(collect_user_data_options,
*profiles[i], *profiles[j]);
});
return profile_indices;
}
int GetDefaultAddressProfile(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles) {
if (profiles.empty()) {
return -1;
}
auto sorted_indices =
SortContactsByCompleteness(collect_user_data_options, profiles);
return sorted_indices[0];
}
std::vector<int> SortPaymentInstrumentsByCompleteness(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<PaymentInstrument>>&
payment_instruments) {
......@@ -146,9 +202,9 @@ std::vector<int> SortByCompleteness(
std::sort(payment_instrument_indices.begin(),
payment_instrument_indices.end(),
[&collect_user_data_options, &payment_instruments](int a, int b) {
return CompletenessCompare(collect_user_data_options,
*payment_instruments[a],
*payment_instruments[b]);
return CompletenessComparePaymentInstruments(
collect_user_data_options, *payment_instruments[a],
*payment_instruments[b]);
});
return payment_instrument_indices;
}
......@@ -160,8 +216,8 @@ int GetDefaultPaymentInstrument(
if (payment_instruments.empty()) {
return -1;
}
auto sorted_indices =
SortByCompleteness(collect_user_data_options, payment_instruments);
auto sorted_indices = SortPaymentInstrumentsByCompleteness(
collect_user_data_options, payment_instruments);
return sorted_indices[0];
}
......
......@@ -16,13 +16,27 @@ namespace autofill_assistant {
// vector of profile indices in sorted order. Full profiles will be ordered
// before empty ones, and for equally complete profiles, this falls back to
// sorting based on the profile names.
std::vector<int> SortByCompleteness(
std::vector<int> SortContactsByCompleteness(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles);
// Get the default selection for the current list of profiles. Returns -1 if no
// default selection is possible.
int GetDefaultProfile(
int GetDefaultContactProfile(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles);
// Sorts the given autofill profiles based on completeness, and returns a
// vector of profile indices in sorted order. Full profiles will be ordered
// before empty ones, and for equally complete profiles, this falls back to
// sorting based on the profile names.
std::vector<int> SortAddressesByCompleteness(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles);
// Get the default selection for the current list of profiles. Returns -1 if no
// default selection is possible.
int GetDefaultAddressProfile(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<autofill::AutofillProfile>>& profiles);
......@@ -30,7 +44,7 @@ int GetDefaultProfile(
// of payment instrument indices in sorted order. Full payment instruments will
// be ordered before empty ones, and for equally complete payment instruments,
// this falls back to sorting based on the full name on the credit card.
std::vector<int> SortByCompleteness(
std::vector<int> SortPaymentInstrumentsByCompleteness(
const CollectUserDataOptions& collect_user_data_options,
const std::vector<std::unique_ptr<PaymentInstrument>>& payment_instruments);
......
......@@ -18,7 +18,7 @@ using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::SizeIs;
TEST(UserDataUtilTest, SortsCompleteProfilesAlphabetically) {
TEST(UserDataUtilTest, SortsCompleteContactsAlphabetically) {
auto profile_a = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_a.get(), "Adam", "", "West",
"adam.west@gmail.com", "", "", "", "", "", "",
......@@ -47,12 +47,12 @@ TEST(UserDataUtilTest, SortsCompleteProfilesAlphabetically) {
options.request_payer_email = true;
std::vector<int> profile_indices =
autofill_assistant::SortByCompleteness(options, profiles);
autofill_assistant::SortContactsByCompleteness(options, profiles);
EXPECT_THAT(profile_indices, SizeIs(profiles.size()));
EXPECT_THAT(profile_indices, ElementsAre(2, 1, 0));
}
TEST(UserDataUtilTest, SortsProfilesByCompleteness) {
TEST(UserDataUtilTest, SortsContactsByCompleteness) {
auto profile_complete = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(
profile_complete.get(), "Charlie", "", "West", "charlie.west@gmail.com",
......@@ -81,19 +81,19 @@ TEST(UserDataUtilTest, SortsProfilesByCompleteness) {
options.request_shipping = true;
std::vector<int> profile_indices =
autofill_assistant::SortByCompleteness(options, profiles);
autofill_assistant::SortContactsByCompleteness(options, profiles);
EXPECT_THAT(profile_indices, SizeIs(profiles.size()));
EXPECT_THAT(profile_indices, ElementsAre(2, 1, 0));
}
TEST(UserDataUtilTest, GetDefaultSelectionForEmptyProfiles) {
TEST(UserDataUtilTest, GetDefaultContactSelectionForEmptyProfiles) {
std::vector<std::unique_ptr<autofill::AutofillProfile>> profiles;
CollectUserDataOptions options;
EXPECT_THAT(GetDefaultProfile(options, profiles), -1);
EXPECT_THAT(GetDefaultContactProfile(options, profiles), -1);
}
TEST(UserDataUtilTest, GetDefaultSelectionForCompleteProfiles) {
TEST(UserDataUtilTest, GetDefaultContactSelectionForCompleteProfiles) {
auto profile_b = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_b.get(), "Berta", "", "West",
"berta.west@gmail.com", "", "", "", "", "", "",
......@@ -113,7 +113,7 @@ TEST(UserDataUtilTest, GetDefaultSelectionForCompleteProfiles) {
options.request_payer_name = true;
options.request_payer_email = true;
EXPECT_THAT(GetDefaultProfile(options, profiles), 1);
EXPECT_THAT(GetDefaultContactProfile(options, profiles), 1);
}
TEST(UserDataUtilTest, GetDefaultSelectionForDefaultEmail) {
......@@ -146,7 +146,89 @@ TEST(UserDataUtilTest, GetDefaultSelectionForDefaultEmail) {
options.request_payer_phone = true;
options.default_email = "adam.west@gmail.com";
EXPECT_THAT(GetDefaultProfile(options, profiles), 2);
EXPECT_THAT(GetDefaultContactProfile(options, profiles), 2);
}
TEST(UserDataUtilTest, SortsCompleteAddressesAlphabetically) {
auto profile_b = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_b.get(), "Berta", "", "West", "", "",
"Brandschenkestrasse 110", "", "Zurich", "",
"8002", "CH", "");
auto profile_a = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_a.get(), "Adam", "", "West", "", "",
"Brandschenkestrasse 110", "", "Zurich", "",
"8002", "CH", "");
// Specify profiles in reverse order to force sorting.
std::vector<std::unique_ptr<autofill::AutofillProfile>> profiles;
profiles.emplace_back(std::move(profile_b));
profiles.emplace_back(std::move(profile_a));
CollectUserDataOptions options;
std::vector<int> profile_indices =
autofill_assistant::SortAddressesByCompleteness(options, profiles);
EXPECT_THAT(profile_indices, SizeIs(profiles.size()));
EXPECT_THAT(profile_indices, ElementsAre(1, 0));
}
TEST(UserDataUtilTest, SortsAddressesByCompleteness) {
// Adding email address and phone number to demonstrate that they are not
// checked for completeness.
auto profile_no_street = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_no_street.get(), "Adam", "", "West",
"adam.west@gmail.com", "", "", "", "Zurich",
"", "8002", "CH", "+41");
auto profile_complete = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_complete.get(), "Berta", "", "West",
"", "", "Brandschenkestrasse 110", "",
"Zurich", "", "8002", "UK", "");
// Specify profiles in reverse order to force sorting.
std::vector<std::unique_ptr<autofill::AutofillProfile>> profiles;
profiles.emplace_back(std::move(profile_no_street));
profiles.emplace_back(std::move(profile_complete));
CollectUserDataOptions options;
std::vector<int> profile_indices =
autofill_assistant::SortAddressesByCompleteness(options, profiles);
EXPECT_THAT(profile_indices, SizeIs(profiles.size()));
EXPECT_THAT(profile_indices, ElementsAre(1, 0));
}
TEST(UserDataUtilTest, GetDefaultAddressSelectionForEmptyProfiles) {
std::vector<std::unique_ptr<autofill::AutofillProfile>> profiles;
CollectUserDataOptions options;
EXPECT_THAT(GetDefaultAddressProfile(options, profiles), -1);
}
TEST(UserDataUtilTest, GetDefaultAddressSelectionForCompleteProfiles) {
// Adding email address and phone number to demonstrate that they are not
// checked for completeness.
auto profile_with_irrelevant_details =
std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_with_irrelevant_details.get(), "Berta",
"berta.west@gmail.com", "West", "", "",
"Brandschenkestrasse 110", "", "Zurich", "",
"8002", "CH", "+41");
auto profile_complete = std::make_unique<autofill::AutofillProfile>();
autofill::test::SetProfileInfo(profile_complete.get(), "Adam", "", "West", "",
"", "Brandschenkestrasse 110", "", "Zurich",
"", "8002", "CH", "");
// Specify profiles in reverse order to force sorting.
std::vector<std::unique_ptr<autofill::AutofillProfile>> profiles;
profiles.emplace_back(std::move(profile_with_irrelevant_details));
profiles.emplace_back(std::move(profile_complete));
CollectUserDataOptions options;
EXPECT_THAT(GetDefaultAddressProfile(options, profiles), 1);
}
TEST(UserDataUtilTest, SortsCreditCardsByCompleteness) {
......@@ -172,7 +254,7 @@ TEST(UserDataUtilTest, SortsCreditCardsByCompleteness) {
CollectUserDataOptions options;
std::vector<int> sorted_indices =
SortByCompleteness(options, payment_instruments);
SortPaymentInstrumentsByCompleteness(options, payment_instruments);
EXPECT_THAT(sorted_indices, SizeIs(payment_instruments.size()));
EXPECT_THAT(sorted_indices, ElementsAre(1, 0));
}
......@@ -200,7 +282,7 @@ TEST(UserDataUtilTest, SortsCompleteCardsByName) {
CollectUserDataOptions options;
std::vector<int> sorted_indices =
SortByCompleteness(options, payment_instruments);
SortPaymentInstrumentsByCompleteness(options, payment_instruments);
EXPECT_THAT(sorted_indices, SizeIs(payment_instruments.size()));
EXPECT_THAT(sorted_indices, ElementsAre(1, 0));
}
......@@ -253,7 +335,7 @@ TEST(UserDataUtilTest, SortsCreditCardsByAddressCompleteness) {
options.require_billing_postal_code = true;
std::vector<int> sorted_indices =
SortByCompleteness(options, payment_instruments);
SortPaymentInstrumentsByCompleteness(options, payment_instruments);
EXPECT_THAT(sorted_indices, SizeIs(payment_instruments.size()));
EXPECT_THAT(sorted_indices, ElementsAre(2, 1, 0));
}
......
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