Commit 2d499d63 authored by Clemens Arbesser's avatar Clemens Arbesser Committed by Commit Bot

[Autofill Assistant] Better default selection of contact profile.

This CL will ensure that by default, the most complete contact profile with the same email address as the one provided for the access token is selected.

Bug: b/140781117
Change-Id: I6a54ddac7190b6aed2f15b848a1a1ca81c684009
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1795325
Commit-Queue: Clemens Arbesser <arbesser@google.com>
Reviewed-by: default avatarMathias Carlen <mcarlen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695160}
parent 028f593d
......@@ -222,7 +222,8 @@ class AssistantCollectUserDataBinder
if (availablePaymentMethods == null) availablePaymentMethods = Collections.emptyList();
view.mPaymentMethodSection.onAvailablePaymentMethodsChanged(availablePaymentMethods);
return true;
} else if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_PROFILES) {
} else if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_PROFILES
|| propertyKey == AssistantCollectUserDataModel.DEFAULT_EMAIL) {
List<PersonalDataManager.AutofillProfile> autofillProfiles =
model.get(AssistantCollectUserDataModel.AVAILABLE_PROFILES);
if (autofillProfiles == null) {
......@@ -232,7 +233,8 @@ class AssistantCollectUserDataBinder
view.mContactDetailsSection.onProfilesChanged(autofillProfiles,
model.get(AssistantCollectUserDataModel.REQUEST_EMAIL),
model.get(AssistantCollectUserDataModel.REQUEST_NAME),
model.get(AssistantCollectUserDataModel.REQUEST_PHONE));
model.get(AssistantCollectUserDataModel.REQUEST_PHONE),
model.get(AssistantCollectUserDataModel.DEFAULT_EMAIL));
}
if (model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
view.mPaymentMethodSection.onProfilesChanged(autofillProfiles);
......
......@@ -59,6 +59,10 @@ public class AssistantCollectUserDataModel extends PropertyModel {
/** The status of the third party terms & conditions. */
public static final WritableIntPropertyKey TERMS_STATUS = new WritableIntPropertyKey();
/** The email address of the preferred profile. */
public static final WritableObjectPropertyKey<String> DEFAULT_EMAIL =
new WritableObjectPropertyKey<>();
public static final WritableBooleanPropertyKey REQUEST_NAME = new WritableBooleanPropertyKey();
public static final WritableBooleanPropertyKey REQUEST_EMAIL = new WritableBooleanPropertyKey();
public static final WritableBooleanPropertyKey REQUEST_PHONE = new WritableBooleanPropertyKey();
......@@ -102,8 +106,8 @@ public class AssistantCollectUserDataModel extends PropertyModel {
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,
LOGIN_SECTION_TITLE, SELECTED_LOGIN, TERMS_STATUS, DEFAULT_EMAIL, 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,
SUPPORTED_BASIC_CARD_NETWORKS, SUPPORTED_PAYMENT_METHODS, AVAILABLE_LOGINS,
......@@ -122,6 +126,7 @@ public class AssistantCollectUserDataModel extends PropertyModel {
set(REQUEST_SHIPPING_ADDRESS, false);
set(REQUEST_LOGIN_CHOICE, false);
set(REQUIRE_BILLING_POSTAL_CODE, false);
set(DEFAULT_EMAIL, "");
}
@CalledByNative
......
......@@ -108,7 +108,7 @@ public class AssistantContactDetailsSection
* set of profiles, while keeping the selected item if possible.
*/
void onProfilesChanged(List<AutofillProfile> profiles, boolean requestPayerEmail,
boolean requestPayerName, boolean requestPayerPhone) {
boolean requestPayerName, boolean requestPayerPhone, String defaultEmail) {
if (mIgnoreProfileChangeNotifications) {
return;
}
......@@ -141,6 +141,17 @@ public class AssistantContactDetailsSection
}
}
// Default selection: select most complete profile with the default email, if possible.
if (selectedContactIndex == -1 && !defaultEmail.isEmpty()) {
// Note: contacts are already sorted by completeness.
for (int i = 0; i < contacts.size(); i++) {
if (TextUtils.equals(contacts.get(i).getPayerEmail(), defaultEmail)) {
selectedContactIndex = i;
break;
}
}
}
// Replace current set of items, keep selection if possible.
setItems(contacts, selectedContactIndex);
}
......
......@@ -683,6 +683,48 @@ public class AutofillAssistantCollectUserDataUiTest {
return viewHolder;
}
/**
* If the default email is set, the most complete profile with that email address should be
* default-selected.
*/
@Test
@MediumTest
public void testDefaultEmail() throws Exception {
AssistantCollectUserDataModel model = new AssistantCollectUserDataModel();
AssistantCollectUserDataCoordinator coordinator = createCollectUserDataCoordinator(model);
AutofillAssistantCollectUserDataTestHelper.MockDelegate delegate =
new AutofillAssistantCollectUserDataTestHelper.MockDelegate();
AutofillAssistantCollectUserDataTestHelper
.ViewHolder viewHolder = TestThreadUtils.runOnUiThreadBlocking(
() -> new AutofillAssistantCollectUserDataTestHelper.ViewHolder(coordinator));
/* Set up fake profiles such that the correct default choice is last. */
mHelper.addDummyProfile("Jane Doe", "jane@gmail.com", "98004");
mHelper.addDummyProfile("", "joe@gmail.com", "");
mHelper.addDummyProfile("Joe Doe", "joe@gmail.com", "98004");
/* Request all PR sections. */
TestThreadUtils.runOnUiThreadBlocking(() -> {
model.set(AssistantCollectUserDataModel.REQUEST_NAME, true);
model.set(AssistantCollectUserDataModel.REQUEST_EMAIL, true);
model.set(AssistantCollectUserDataModel.DEFAULT_EMAIL, "joe@gmail.com");
model.set(AssistantCollectUserDataModel.DELEGATE, delegate);
model.set(AssistantCollectUserDataModel.VISIBLE, true);
});
for (int i = 0; i < viewHolder.mContactList.getItemCount(); i++) {
if (viewHolder.mContactList.isChecked(viewHolder.mContactList.getItem(i))) {
testContact("joe@gmail.com", "Joe Doe\njoe@gmail.com",
viewHolder.mContactSection.getCollapsedView(),
viewHolder.mContactList.getItem(i));
break;
}
}
assertThat(delegate.mContact.getPayerEmail(), is("joe@gmail.com"));
assertThat(delegate.mContact.getPayerName(), is("Joe Doe"));
}
private View getPaymentSummaryErrorView(ViewHolder viewHolder) {
return viewHolder.mPaymentSection.findViewById(R.id.payment_method_summary)
.findViewById(R.id.incomplete_error);
......
......@@ -262,6 +262,10 @@ class ActionDelegate {
// Get associated web contents.
virtual content::WebContents* GetWebContents() = 0;
// Returns the e-mail address that corresponds to the access token or an empty
// string.
virtual std::string GetAccountEmailAddress() = 0;
// Sets or updates contextual information.
// Passing nullptr clears the contextual information.
virtual void SetDetails(std::unique_ptr<Details> details) = 0;
......
......@@ -403,6 +403,9 @@ CollectUserDataAction::CreateOptionsFromProto() {
}
}
collect_user_data_options->default_email =
delegate_->GetAccountEmailAddress();
return collect_user_data_options;
}
......
......@@ -200,6 +200,7 @@ class MockActionDelegate : public ActionDelegate {
MOCK_METHOD0(GetPersonalDataManager, autofill::PersonalDataManager*());
MOCK_METHOD0(GetWebsiteLoginFetcher, WebsiteLoginFetcher*());
MOCK_METHOD0(GetWebContents, content::WebContents*());
MOCK_METHOD0(GetAccountEmailAddress, std::string());
MOCK_METHOD1(SetDetails, void(std::unique_ptr<Details> details));
MOCK_METHOD1(SetInfoBox, void(const InfoBox& info_box));
MOCK_METHOD0(ClearInfoBox, void());
......
......@@ -152,6 +152,10 @@ content::WebContents* Controller::GetWebContents() {
return web_contents();
}
std::string Controller::GetAccountEmailAddress() {
return client_->GetAccountEmailAddress();
}
void Controller::SetTouchableElementArea(const ElementAreaProto& area) {
touchable_element_area()->SetFromProto(area);
}
......
......@@ -98,6 +98,7 @@ class Controller : public ScriptExecutorDelegate,
autofill::PersonalDataManager* GetPersonalDataManager() override;
WebsiteLoginFetcher* GetWebsiteLoginFetcher() override;
content::WebContents* GetWebContents() override;
std::string GetAccountEmailAddress() override;
void SetTouchableElementArea(const ElementAreaProto& area) override;
void SetStatusMessage(const std::string& message) override;
std::string GetStatusMessage() const override;
......
......@@ -54,6 +54,10 @@ content::WebContents* FakeScriptExecutorDelegate::GetWebContents() {
return nullptr;
}
std::string FakeScriptExecutorDelegate::GetAccountEmailAddress() {
return std::string();
}
void FakeScriptExecutorDelegate::EnterState(AutofillAssistantState state) {
state_ = state;
}
......
......@@ -35,6 +35,7 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
autofill::PersonalDataManager* GetPersonalDataManager() override;
WebsiteLoginFetcher* GetWebsiteLoginFetcher() override;
content::WebContents* GetWebContents() override;
std::string GetAccountEmailAddress() override;
void EnterState(AutofillAssistantState state) override;
void SetTouchableElementArea(const ElementAreaProto& element) override;
void SetStatusMessage(const std::string& message) override;
......
......@@ -499,6 +499,10 @@ content::WebContents* ScriptExecutor::GetWebContents() {
return delegate_->GetWebContents();
}
std::string ScriptExecutor::GetAccountEmailAddress() {
return delegate_->GetAccountEmailAddress();
}
void ScriptExecutor::SetDetails(std::unique_ptr<Details> details) {
return delegate_->SetDetails(std::move(details));
}
......
......@@ -190,6 +190,7 @@ class ScriptExecutor : public ActionDelegate,
autofill::PersonalDataManager* GetPersonalDataManager() override;
WebsiteLoginFetcher* GetWebsiteLoginFetcher() override;
content::WebContents* GetWebContents() override;
std::string GetAccountEmailAddress() override;
void SetDetails(std::unique_ptr<Details> details) override;
void ClearInfoBox() override;
void SetInfoBox(const InfoBox& info_box) override;
......
......@@ -54,6 +54,7 @@ class ScriptExecutorDelegate {
virtual autofill::PersonalDataManager* GetPersonalDataManager() = 0;
virtual WebsiteLoginFetcher* GetWebsiteLoginFetcher() = 0;
virtual content::WebContents* GetWebContents() = 0;
virtual std::string GetAccountEmailAddress() = 0;
virtual void EnterState(AutofillAssistantState state) = 0;
// Make the area of the screen that correspond to the given elements
......
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