Commit aee6fd2b authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

[Contacts] Use ContactsContract API in Android to get Address info.

Grab address info in the contacts fetcher task, and pipe down to the
address provider to create a mojo address object.

Bug: 1016870
Change-Id: I4d0580f0c27cbaef813cb2374b010ad182cb64d4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1879240Reviewed-by: default avatarFinnur Thorarinsson <finnur@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarMohamed Heikal <mheikal@chromium.org>
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Cr-Commit-Position: refs/heads/master@{#711285}
parent ac1bf595
...@@ -9,6 +9,7 @@ import android.content.res.Resources; ...@@ -9,6 +9,7 @@ import android.content.res.Resources;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.payments.mojom.PaymentAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
...@@ -42,19 +43,24 @@ public class ContactDetails implements Comparable<ContactDetails> { ...@@ -42,19 +43,24 @@ public class ContactDetails implements Comparable<ContactDetails> {
// The list of phone numbers registered for this contact. // The list of phone numbers registered for this contact.
private final List<String> mPhoneNumbers; private final List<String> mPhoneNumbers;
// The list of addresses registered for this contact.
private final List<PaymentAddress> mAddresses;
/** /**
* The ContactDetails constructor. * The ContactDetails constructor.
* @param id The unique identifier of this contact. * @param id The unique identifier of this contact.
* @param displayName The display name of this contact. * @param displayName The display name of this contact.
* @param emails The emails registered for this contact. * @param emails The emails registered for this contact.
* @param phoneNumbers The phone numbers registered for this contact. * @param phoneNumbers The phone numbers registered for this contact.
* @param addresses The addresses registered for this contact.
*/ */
public ContactDetails( public ContactDetails(String id, String displayName, List<String> emails,
String id, String displayName, List<String> emails, List<String> phoneNumbers) { List<String> phoneNumbers, List<PaymentAddress> addresses) {
mDisplayName = displayName; mDisplayName = displayName;
mEmails = emails != null ? new ArrayList<String>(emails) : new ArrayList<String>(); mEmails = emails != null ? emails : new ArrayList<String>();
mPhoneNumbers = phoneNumbers != null ? new ArrayList<String>(phoneNumbers) mPhoneNumbers = phoneNumbers != null ? phoneNumbers : new ArrayList<String>();
: new ArrayList<String>(); mAddresses = addresses != null ? addresses : new ArrayList<PaymentAddress>();
mId = id; mId = id;
} }
...@@ -70,6 +76,10 @@ public class ContactDetails implements Comparable<ContactDetails> { ...@@ -70,6 +76,10 @@ public class ContactDetails implements Comparable<ContactDetails> {
return mPhoneNumbers; return mPhoneNumbers;
} }
public List<PaymentAddress> getAddresses() {
return mAddresses;
}
public String getDisplayName() { public String getDisplayName() {
return mDisplayName; return mDisplayName;
} }
......
...@@ -11,6 +11,7 @@ import android.provider.ContactsContract; ...@@ -11,6 +11,7 @@ import android.provider.ContactsContract;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.task.AsyncTask; import org.chromium.base.task.AsyncTask;
import org.chromium.payments.mojom.PaymentAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
...@@ -52,6 +53,9 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> { ...@@ -52,6 +53,9 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> {
// Whether to include telephones in the data fetched. // Whether to include telephones in the data fetched.
private final boolean mIncludeTel; private final boolean mIncludeTel;
// Whether to include addresses in the data fetched.
private final boolean mIncludeAddresses;
/** /**
* A ContactsFetcherWorkerTask constructor. * A ContactsFetcherWorkerTask constructor.
* @param contentResolver The ContentResolver to use to fetch the contacts data. * @param contentResolver The ContentResolver to use to fetch the contacts data.
...@@ -59,15 +63,17 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> { ...@@ -59,15 +63,17 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> {
* @param includeNames Whether names were requested by the website. * @param includeNames Whether names were requested by the website.
* @param includeEmails Whether to include emails in the data fetched. * @param includeEmails Whether to include emails in the data fetched.
* @param includeTel Whether to include telephones in the data fetched. * @param includeTel Whether to include telephones in the data fetched.
* @param includeAddresses Whether to include telephones in the data fetched.
*/ */
public ContactsFetcherWorkerTask(ContentResolver contentResolver, public ContactsFetcherWorkerTask(ContentResolver contentResolver,
ContactsRetrievedCallback callback, boolean includeNames, boolean includeEmails, ContactsRetrievedCallback callback, boolean includeNames, boolean includeEmails,
boolean includeTel) { boolean includeTel, boolean includeAddresses) {
mContentResolver = contentResolver; mContentResolver = contentResolver;
mCallback = callback; mCallback = callback;
mIncludeNames = includeNames; mIncludeNames = includeNames;
mIncludeEmails = includeEmails; mIncludeEmails = includeEmails;
mIncludeTel = includeTel; mIncludeTel = includeTel;
mIncludeAddresses = includeAddresses;
} }
/** /**
...@@ -103,6 +109,7 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> { ...@@ -103,6 +109,7 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
String id = cursor.getString(cursor.getColumnIndex(idColumn)); String id = cursor.getString(cursor.getColumnIndex(idColumn));
value = cursor.getString(cursor.getColumnIndex(dataColumn)); value = cursor.getString(cursor.getColumnIndex(dataColumn));
if (value == null) value = "";
if (key.isEmpty()) { if (key.isEmpty()) {
key = id; key = id;
list.add(value); list.add(value);
...@@ -123,6 +130,76 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> { ...@@ -123,6 +130,76 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> {
return map; return map;
} }
/** Creates a PaymentAddress mojo struct. */
private PaymentAddress createAddress(
String city, String country, String formattedAddress, String postcode, String region) {
PaymentAddress address = new PaymentAddress();
address.city = city != null ? city : "";
address.country = country != null ? country : "";
address.addressLine =
formattedAddress != null ? new String[] {formattedAddress} : new String[] {};
address.postalCode = postcode != null ? postcode : "";
address.region = region != null ? region : "";
// The other fields are required.
address.dependentLocality = "";
address.sortingCode = "";
address.organization = "";
address.recipient = "";
address.phone = "";
return address;
}
/** Fetches all available address info for contacts. */
private Map<String, ArrayList<PaymentAddress>> getAddressDetails() {
Map<String, ArrayList<PaymentAddress>> map = new HashMap<>();
String addressSortOrder = ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID
+ " ASC, " + ContactsContract.CommonDataKinds.StructuredPostal.DATA + " ASC";
Cursor cursor = mContentResolver.query(
ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI, null, null, null,
addressSortOrder);
ArrayList<PaymentAddress> list = new ArrayList<>();
String key = "";
while (cursor.moveToNext()) {
String id = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID));
String city = cursor.getString(
cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
String country = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
String formattedAddress = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS));
String postcode = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
String region = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredPostal.REGION));
PaymentAddress address =
createAddress(city, country, formattedAddress, postcode, region);
if (key.isEmpty()) {
key = id;
list.add(address);
} else {
if (key.equals(id)) {
list.add(address);
} else {
map.put(key, list);
list = new ArrayList<>();
list.add(address);
key = id;
}
}
}
map.put(key, list);
cursor.close();
return map;
}
/** /**
* Fetches all known contacts. * Fetches all known contacts.
* @return The contact list as an array. * @return The contact list as an array.
...@@ -139,11 +216,14 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> { ...@@ -139,11 +216,14 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> {
Map<String, ArrayList<String>> phoneMap = mIncludeTel Map<String, ArrayList<String>> phoneMap = mIncludeTel
? getDetails(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, ? getDetails(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID, ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Email.DATA, ContactsContract.CommonDataKinds.Phone.DATA,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " ASC, " ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " ASC, "
+ ContactsContract.CommonDataKinds.Phone.NUMBER + " ASC") + ContactsContract.CommonDataKinds.Phone.NUMBER + " ASC")
: null; : null;
Map<String, ArrayList<PaymentAddress>> addressMap =
mIncludeAddresses ? getAddressDetails() : null;
// A cursor containing the raw contacts data. // A cursor containing the raw contacts data.
Cursor cursor = mContentResolver.query(ContactsContract.Contacts.CONTENT_URI, PROJECTION, Cursor cursor = mContentResolver.query(ContactsContract.Contacts.CONTENT_URI, PROJECTION,
null, null, ContactsContract.Contacts.SORT_KEY_PRIMARY + " ASC"); null, null, ContactsContract.Contacts.SORT_KEY_PRIMARY + " ASC");
...@@ -156,8 +236,11 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> { ...@@ -156,8 +236,11 @@ class ContactsFetcherWorkerTask extends AsyncTask<ArrayList<ContactDetails>> {
cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)); cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
List<String> email = mIncludeEmails ? emailMap.get(id) : null; List<String> email = mIncludeEmails ? emailMap.get(id) : null;
List<String> tel = mIncludeTel ? phoneMap.get(id) : null; List<String> tel = mIncludeTel ? phoneMap.get(id) : null;
if (mIncludeNames || email != null || tel != null) List<PaymentAddress> address = mIncludeAddresses ? addressMap.get(id) : null;
contacts.add(new ContactDetails(id, name, email, tel));
if (mIncludeNames || email != null || tel != null || address != null) {
contacts.add(new ContactDetails(id, name, email, tel, address));
}
} while (cursor.moveToNext()); } while (cursor.moveToNext());
cursor.close(); cursor.close();
......
...@@ -28,17 +28,18 @@ public class ContactsPickerDialog ...@@ -28,17 +28,18 @@ public class ContactsPickerDialog
* @param includeNames Whether the contacts data returned includes names. * @param includeNames Whether the contacts data returned includes names.
* @param includeEmails Whether the contacts data returned includes emails. * @param includeEmails Whether the contacts data returned includes emails.
* @param includeTel Whether the contacts data returned includes telephone numbers. * @param includeTel Whether the contacts data returned includes telephone numbers.
* @param includeAddresses Whether the contacts data returned includes addresses.
* @param formattedOrigin The origin the data will be shared with, formatted for display with * @param formattedOrigin The origin the data will be shared with, formatted for display with
* the scheme omitted. * the scheme omitted.
*/ */
public ContactsPickerDialog(Context context, ContactsPickerListener listener, public ContactsPickerDialog(Context context, ContactsPickerListener listener,
boolean allowMultiple, boolean includeNames, boolean includeEmails, boolean includeTel, boolean allowMultiple, boolean includeNames, boolean includeEmails, boolean includeTel,
String formattedOrigin) { boolean includeAddresses, String formattedOrigin) {
super(context, R.style.Theme_Chromium_Fullscreen); super(context, R.style.Theme_Chromium_Fullscreen);
// Initialize the main content view. // Initialize the main content view.
mCategoryView = new PickerCategoryView(context, allowMultiple, includeNames, includeEmails, mCategoryView = new PickerCategoryView(context, allowMultiple, includeNames, includeEmails,
includeTel, formattedOrigin, this); includeTel, includeAddresses, formattedOrigin, this);
mCategoryView.initialize(this, listener); mCategoryView.initialize(this, listener);
setView(mCategoryView); setView(mCategoryView);
} }
......
...@@ -124,7 +124,7 @@ public class PickerAdapter extends Adapter<RecyclerView.ViewHolder> ...@@ -124,7 +124,7 @@ public class PickerAdapter extends Adapter<RecyclerView.ViewHolder>
if (getAllContacts() == null && sTestContacts == null) { if (getAllContacts() == null && sTestContacts == null) {
mWorkerTask = new ContactsFetcherWorkerTask(mContentResolver, this, mWorkerTask = new ContactsFetcherWorkerTask(mContentResolver, this,
mCategoryView.includeNames, mCategoryView.includeEmails, mCategoryView.includeNames, mCategoryView.includeEmails,
mCategoryView.includeTel); mCategoryView.includeTel, mCategoryView.includeAddresses);
mWorkerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); mWorkerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else { } else {
mContactDetails = sTestContacts; mContactDetails = sTestContacts;
......
...@@ -113,6 +113,9 @@ public class PickerCategoryView extends OptimizedFrameLayout ...@@ -113,6 +113,9 @@ public class PickerCategoryView extends OptimizedFrameLayout
// Whether the contacts data returned includes telephone numbers. // Whether the contacts data returned includes telephone numbers.
public final boolean includeTel; public final boolean includeTel;
// Whether the contacts data returned includes addresses.
public final boolean includeAddresses;
/** /**
* @param multiSelectionAllowed Whether the contacts picker should allow multiple items to be * @param multiSelectionAllowed Whether the contacts picker should allow multiple items to be
* selected. * selected.
...@@ -120,7 +123,8 @@ public class PickerCategoryView extends OptimizedFrameLayout ...@@ -120,7 +123,8 @@ public class PickerCategoryView extends OptimizedFrameLayout
@SuppressWarnings("unchecked") // mSelectableListLayout @SuppressWarnings("unchecked") // mSelectableListLayout
public PickerCategoryView(Context context, boolean multiSelectionAllowed, public PickerCategoryView(Context context, boolean multiSelectionAllowed,
boolean shouldIncludeNames, boolean shouldIncludeEmails, boolean shouldIncludeTel, boolean shouldIncludeNames, boolean shouldIncludeEmails, boolean shouldIncludeTel,
String formattedOrigin, ContactsPickerToolbar.ContactsToolbarDelegate delegate) { boolean shouldIncludeAddresses, String formattedOrigin,
ContactsPickerToolbar.ContactsToolbarDelegate delegate) {
super(context, null); super(context, null);
mActivity = (ChromeActivity) context; mActivity = (ChromeActivity) context;
...@@ -128,6 +132,7 @@ public class PickerCategoryView extends OptimizedFrameLayout ...@@ -128,6 +132,7 @@ public class PickerCategoryView extends OptimizedFrameLayout
includeNames = shouldIncludeNames; includeNames = shouldIncludeNames;
includeEmails = shouldIncludeEmails; includeEmails = shouldIncludeEmails;
includeTel = shouldIncludeTel; includeTel = shouldIncludeTel;
includeAddresses = shouldIncludeAddresses;
mSelectionDelegate = new SelectionDelegate<ContactDetails>(); mSelectionDelegate = new SelectionDelegate<ContactDetails>();
if (!multiSelectionAllowed) mSelectionDelegate.setSingleSelectionMode(); if (!multiSelectionAllowed) mSelectionDelegate.setSingleSelectionMode();
...@@ -326,8 +331,8 @@ public class PickerCategoryView extends OptimizedFrameLayout ...@@ -326,8 +331,8 @@ public class PickerCategoryView extends OptimizedFrameLayout
* @param selected The property values that are currently selected. * @param selected The property values that are currently selected.
* @return The list of property values to share. * @return The list of property values to share.
*/ */
private List<String> getContactPropertyValues( private <T> List<T> getContactPropertyValues(
boolean isIncluded, boolean isEnabled, List<String> selected) { boolean isIncluded, boolean isEnabled, List<T> selected) {
if (!isIncluded) { if (!isIncluded) {
// The property wasn't requested in the API so return null. // The property wasn't requested in the API so return null.
return null; return null;
...@@ -335,7 +340,7 @@ public class PickerCategoryView extends OptimizedFrameLayout ...@@ -335,7 +340,7 @@ public class PickerCategoryView extends OptimizedFrameLayout
if (!isEnabled) { if (!isEnabled) {
// The user doesn't want to share this property, so return an empty array. // The user doesn't want to share this property, so return an empty array.
return new ArrayList<String>(); return new ArrayList<T>();
} }
// Share whatever was selected. // Share whatever was selected.
...@@ -359,7 +364,10 @@ public class PickerCategoryView extends OptimizedFrameLayout ...@@ -359,7 +364,10 @@ public class PickerCategoryView extends OptimizedFrameLayout
getContactPropertyValues(includeEmails, PickerAdapter.includesEmails(), getContactPropertyValues(includeEmails, PickerAdapter.includesEmails(),
contactDetails.getEmails()), contactDetails.getEmails()),
getContactPropertyValues(includeTel, PickerAdapter.includesTelephones(), getContactPropertyValues(includeTel, PickerAdapter.includesTelephones(),
contactDetails.getPhoneNumbers()))); contactDetails.getPhoneNumbers()),
// TODO(crbug.com/1016870): Check the address chip when added.
getContactPropertyValues(
includeAddresses, true, contactDetails.getAddresses())));
} }
executeAction(ContactsPickerListener.ContactsPickerAction.CONTACTS_SELECTED, contacts, executeAction(ContactsPickerListener.ContactsPickerAction.CONTACTS_SELECTED, contacts,
ACTION_CONTACTS_SELECTED); ACTION_CONTACTS_SELECTED);
...@@ -383,6 +391,9 @@ public class PickerCategoryView extends OptimizedFrameLayout ...@@ -383,6 +391,9 @@ public class PickerCategoryView extends OptimizedFrameLayout
propertiesRequested |= ContactsPickerPropertiesRequested.PROPERTIES_EMAILS; propertiesRequested |= ContactsPickerPropertiesRequested.PROPERTIES_EMAILS;
} }
if (includeTel) propertiesRequested |= ContactsPickerPropertiesRequested.PROPERTIES_TELS; if (includeTel) propertiesRequested |= ContactsPickerPropertiesRequested.PROPERTIES_TELS;
if (includeAddresses) {
propertiesRequested |= ContactsPickerPropertiesRequested.PROPERTIES_ADDRESSES;
}
mListener.onContactsPickerUserAction( mListener.onContactsPickerUserAction(
action, contacts, percentageShared, propertiesRequested); action, contacts, percentageShared, propertiesRequested);
......
...@@ -260,9 +260,9 @@ public class ProcessInitializationHandler { ...@@ -260,9 +260,9 @@ public class ProcessInitializationHandler {
@Override @Override
public void showContactsPicker(Context context, ContactsPickerListener listener, public void showContactsPicker(Context context, ContactsPickerListener listener,
boolean allowMultiple, boolean includeNames, boolean includeEmails, boolean allowMultiple, boolean includeNames, boolean includeEmails,
boolean includeTel, String formattedOrigin) { boolean includeTel, boolean includeAddresses, String formattedOrigin) {
mDialog = new ContactsPickerDialog(context, listener, allowMultiple, includeNames, mDialog = new ContactsPickerDialog(context, listener, allowMultiple, includeNames,
includeEmails, includeTel, formattedOrigin); includeEmails, includeTel, includeAddresses, formattedOrigin);
mDialog.getWindow().getAttributes().windowAnimations = mDialog.getWindow().getAttributes().windowAnimations =
R.style.PickerDialogAnimation; R.style.PickerDialogAnimation;
mDialog.show(); mDialog.show();
......
...@@ -34,6 +34,7 @@ import org.chromium.chrome.test.util.browser.Features; ...@@ -34,6 +34,7 @@ import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils; import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.content_public.browser.test.util.TestTouchUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils;
import org.chromium.payments.mojom.PaymentAddress;
import org.chromium.ui.ContactsPickerListener; import org.chromium.ui.ContactsPickerListener;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -94,13 +95,31 @@ public class ContactsPickerDialogTest ...@@ -94,13 +95,31 @@ public class ContactsPickerDialogTest
public void setUp() throws Exception { public void setUp() throws Exception {
mActivityTestRule.startMainActivityOnBlankPage(); mActivityTestRule.startMainActivityOnBlankPage();
mTestContacts = new ArrayList<ContactDetails>(); mTestContacts = new ArrayList<ContactDetails>();
mTestContacts.add(new ContactDetails(
"0", "Contact 0", Arrays.asList("0@example.com"), Arrays.asList("555-1234"))); PaymentAddress address = new PaymentAddress();
mTestContacts.add(new ContactDetails("1", "Contact 1", null, null)); address.city = "city";
mTestContacts.add(new ContactDetails("2", "Contact 2", null, null)); address.country = "country";
mTestContacts.add(new ContactDetails("3", "Contact 3", null, null)); address.addressLine = new String[] {"formattedAddress"};
mTestContacts.add(new ContactDetails("4", "Contact 4", null, null)); address.postalCode = "postalCode";
mTestContacts.add(new ContactDetails("5", "Contact 5", null, null)); address.region = "region";
address.dependentLocality = "";
address.sortingCode = "";
address.organization = "";
address.recipient = "";
address.phone = "";
mTestContacts.add(new ContactDetails("0", "Contact 0", Arrays.asList("0@example.com"),
Arrays.asList("555-1234"), Arrays.asList(address)));
mTestContacts.add(new ContactDetails("1", "Contact 1", /*emails=*/null,
/*phoneNumbers=*/null, /*addresses=*/null));
mTestContacts.add(new ContactDetails("2", "Contact 2", /*emails=*/null,
/*phoneNumbers=*/null, /*addresses=*/null));
mTestContacts.add(new ContactDetails("3", "Contact 3", /*emails=*/null,
/*phoneNumbers=*/null, /*addresses=*/null));
mTestContacts.add(new ContactDetails("4", "Contact 4", /*emails=*/null,
/*phoneNumbers=*/null, /*addresses=*/null));
mTestContacts.add(new ContactDetails("5", "Contact 5", /*emails=*/null,
/*phoneNumbers=*/null, /*addresses=*/null));
PickerAdapter.setTestContacts(mTestContacts); PickerAdapter.setTestContacts(mTestContacts);
Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
...@@ -135,7 +154,8 @@ public class ContactsPickerDialogTest ...@@ -135,7 +154,8 @@ public class ContactsPickerDialogTest
} }
private ContactsPickerDialog createDialog(final boolean multiselect, final boolean includeNames, private ContactsPickerDialog createDialog(final boolean multiselect, final boolean includeNames,
final boolean includeEmails, final boolean includeTel) throws Exception { final boolean includeEmails, final boolean includeTel, final boolean includeAddresses)
throws Exception {
mClosing = false; mClosing = false;
final ContactsPickerDialog dialog = final ContactsPickerDialog dialog =
TestThreadUtils.runOnUiThreadBlocking(new Callable<ContactsPickerDialog>() { TestThreadUtils.runOnUiThreadBlocking(new Callable<ContactsPickerDialog>() {
...@@ -144,7 +164,7 @@ public class ContactsPickerDialogTest ...@@ -144,7 +164,7 @@ public class ContactsPickerDialogTest
final ContactsPickerDialog dialog = final ContactsPickerDialog dialog =
new ContactsPickerDialog(mActivityTestRule.getActivity(), new ContactsPickerDialog(mActivityTestRule.getActivity(),
ContactsPickerDialogTest.this, multiselect, includeNames, ContactsPickerDialogTest.this, multiselect, includeNames,
includeEmails, includeTel, "example.com"); includeEmails, includeTel, includeAddresses, "example.com");
dialog.show(); dialog.show();
return dialog; return dialog;
} }
...@@ -273,7 +293,8 @@ public class ContactsPickerDialogTest ...@@ -273,7 +293,8 @@ public class ContactsPickerDialogTest
public void testOriginString() throws Throwable { public void testOriginString() throws Throwable {
createDialog(/* multiselect = */ true, /* includeNames = */ true, createDialog(/* multiselect = */ true, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
TopView topView = getTopView(); TopView topView = getTopView();
...@@ -292,7 +313,8 @@ public class ContactsPickerDialogTest ...@@ -292,7 +313,8 @@ public class ContactsPickerDialogTest
public void testFilterVisibilityForDataInclusion() throws Throwable { public void testFilterVisibilityForDataInclusion() throws Throwable {
createDialog(/* multiselect = */ false, /* includeNames = */ true, createDialog(/* multiselect = */ false, /* includeNames = */ true,
/* includeEmails = */ false, /* includeEmails = */ false,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ false);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
TopView topView = getTopView(); TopView topView = getTopView();
...@@ -310,6 +332,7 @@ public class ContactsPickerDialogTest ...@@ -310,6 +332,7 @@ public class ContactsPickerDialogTest
Assert.assertEquals(namesFilter.getVisibility(), View.VISIBLE); Assert.assertEquals(namesFilter.getVisibility(), View.VISIBLE);
Assert.assertEquals(emailFilter.getVisibility(), View.GONE); Assert.assertEquals(emailFilter.getVisibility(), View.GONE);
Assert.assertEquals(telFilter.getVisibility(), View.VISIBLE); Assert.assertEquals(telFilter.getVisibility(), View.VISIBLE);
// TODO(crbug.com/1016870): Add a false test for the filter chip, when added.
} }
@Test @Test
...@@ -317,7 +340,8 @@ public class ContactsPickerDialogTest ...@@ -317,7 +340,8 @@ public class ContactsPickerDialogTest
public void testNoSelection() throws Throwable { public void testNoSelection() throws Throwable {
createDialog(/* multiselect = */ false, /* includeNames = */ true, createDialog(/* multiselect = */ false, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
int expectedSelectionCount = 1; int expectedSelectionCount = 1;
...@@ -326,7 +350,7 @@ public class ContactsPickerDialogTest ...@@ -326,7 +350,7 @@ public class ContactsPickerDialogTest
Assert.assertEquals(null, mLastSelectedContacts); Assert.assertEquals(null, mLastSelectedContacts);
Assert.assertEquals(0, mLastPercentageShared); Assert.assertEquals(0, mLastPercentageShared);
Assert.assertEquals(7, mLastPropertiesRequested); Assert.assertEquals(15, mLastPropertiesRequested);
Assert.assertEquals(ContactsPickerAction.CANCEL, mLastActionRecorded); Assert.assertEquals(ContactsPickerAction.CANCEL, mLastActionRecorded);
} }
...@@ -335,7 +359,8 @@ public class ContactsPickerDialogTest ...@@ -335,7 +359,8 @@ public class ContactsPickerDialogTest
public void testSingleSelectionContacts() throws Throwable { public void testSingleSelectionContacts() throws Throwable {
createDialog(/* multiselect = */ false, /* includeNames = */ true, createDialog(/* multiselect = */ false, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
// Expected selection count is 1 because clicking on a new view deselects other. // Expected selection count is 1 because clicking on a new view deselects other.
...@@ -349,7 +374,7 @@ public class ContactsPickerDialogTest ...@@ -349,7 +374,7 @@ public class ContactsPickerDialogTest
Assert.assertEquals( Assert.assertEquals(
mTestContacts.get(1).getDisplayName(), mLastSelectedContacts.get(0).names.get(0)); mTestContacts.get(1).getDisplayName(), mLastSelectedContacts.get(0).names.get(0));
Assert.assertEquals(16, mLastPercentageShared); Assert.assertEquals(16, mLastPercentageShared);
Assert.assertEquals(7, mLastPropertiesRequested); Assert.assertEquals(15, mLastPropertiesRequested);
} }
@Test @Test
...@@ -357,7 +382,8 @@ public class ContactsPickerDialogTest ...@@ -357,7 +382,8 @@ public class ContactsPickerDialogTest
public void testMultiSelectionContacts() throws Throwable { public void testMultiSelectionContacts() throws Throwable {
createDialog(/* multiselect = */ true, /* includeNames = */ true, createDialog(/* multiselect = */ true, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
// Multi-selection is enabled, so each click is counted. // Multi-selection is enabled, so each click is counted.
...@@ -376,7 +402,7 @@ public class ContactsPickerDialogTest ...@@ -376,7 +402,7 @@ public class ContactsPickerDialogTest
Assert.assertEquals( Assert.assertEquals(
mTestContacts.get(0).getDisplayName(), mLastSelectedContacts.get(2).names.get(0)); mTestContacts.get(0).getDisplayName(), mLastSelectedContacts.get(2).names.get(0));
Assert.assertEquals(50, mLastPercentageShared); Assert.assertEquals(50, mLastPercentageShared);
Assert.assertEquals(7, mLastPropertiesRequested); Assert.assertEquals(15, mLastPropertiesRequested);
} }
@Test @Test
...@@ -384,7 +410,8 @@ public class ContactsPickerDialogTest ...@@ -384,7 +410,8 @@ public class ContactsPickerDialogTest
public void testNamesRemoved() throws Throwable { public void testNamesRemoved() throws Throwable {
createDialog(/* multiselect = */ false, /* includeNames = */ true, createDialog(/* multiselect = */ false, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
toggleFilter(PickerAdapter.FilterType.NAMES); toggleFilter(PickerAdapter.FilterType.NAMES);
...@@ -398,8 +425,20 @@ public class ContactsPickerDialogTest ...@@ -398,8 +425,20 @@ public class ContactsPickerDialogTest
Assert.assertEquals(new ArrayList<String>(), mLastSelectedContacts.get(0).names); Assert.assertEquals(new ArrayList<String>(), mLastSelectedContacts.get(0).names);
Assert.assertEquals(mTestContacts.get(0).getEmails().get(0), Assert.assertEquals(mTestContacts.get(0).getEmails().get(0),
mLastSelectedContacts.get(0).emails.get(0)); mLastSelectedContacts.get(0).emails.get(0));
Assert.assertEquals(mTestContacts.get(0).getPhoneNumbers().get(0),
mLastSelectedContacts.get(0).tel.get(0));
PaymentAddress selectedAddress =
PaymentAddress.deserialize(mLastSelectedContacts.get(0).serializedAddresses.get(0));
PaymentAddress testAddress = mTestContacts.get(0).getAddresses().get(0);
Assert.assertEquals(selectedAddress.city, testAddress.city);
Assert.assertEquals(selectedAddress.country, testAddress.country);
Assert.assertEquals(selectedAddress.addressLine[0], testAddress.addressLine[0]);
Assert.assertEquals(selectedAddress.postalCode, testAddress.postalCode);
Assert.assertEquals(selectedAddress.region, testAddress.region);
Assert.assertEquals(16, mLastPercentageShared); Assert.assertEquals(16, mLastPercentageShared);
Assert.assertEquals(7, mLastPropertiesRequested); Assert.assertEquals(15, mLastPropertiesRequested);
} }
@Test @Test
...@@ -407,7 +446,8 @@ public class ContactsPickerDialogTest ...@@ -407,7 +446,8 @@ public class ContactsPickerDialogTest
public void testEmailsRemoved() throws Throwable { public void testEmailsRemoved() throws Throwable {
createDialog(/* multiselect = */ false, /* includeNames = */ true, createDialog(/* multiselect = */ false, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
toggleFilter(PickerAdapter.FilterType.EMAILS); toggleFilter(PickerAdapter.FilterType.EMAILS);
...@@ -422,7 +462,7 @@ public class ContactsPickerDialogTest ...@@ -422,7 +462,7 @@ public class ContactsPickerDialogTest
mTestContacts.get(0).getDisplayName(), mLastSelectedContacts.get(0).names.get(0)); mTestContacts.get(0).getDisplayName(), mLastSelectedContacts.get(0).names.get(0));
Assert.assertEquals(new ArrayList<String>(), mLastSelectedContacts.get(0).emails); Assert.assertEquals(new ArrayList<String>(), mLastSelectedContacts.get(0).emails);
Assert.assertEquals(16, mLastPercentageShared); Assert.assertEquals(16, mLastPercentageShared);
Assert.assertEquals(7, mLastPropertiesRequested); Assert.assertEquals(15, mLastPropertiesRequested);
} }
@Test @Test
...@@ -430,7 +470,8 @@ public class ContactsPickerDialogTest ...@@ -430,7 +470,8 @@ public class ContactsPickerDialogTest
public void testTelephonesRemoved() throws Throwable { public void testTelephonesRemoved() throws Throwable {
createDialog(/* multiselect = */ false, /* includeNames = */ true, createDialog(/* multiselect = */ false, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
toggleFilter(PickerAdapter.FilterType.TELEPHONES); toggleFilter(PickerAdapter.FilterType.TELEPHONES);
...@@ -445,7 +486,7 @@ public class ContactsPickerDialogTest ...@@ -445,7 +486,7 @@ public class ContactsPickerDialogTest
mTestContacts.get(0).getDisplayName(), mLastSelectedContacts.get(0).names.get(0)); mTestContacts.get(0).getDisplayName(), mLastSelectedContacts.get(0).names.get(0));
Assert.assertEquals(new ArrayList<String>(), mLastSelectedContacts.get(0).tel); Assert.assertEquals(new ArrayList<String>(), mLastSelectedContacts.get(0).tel);
Assert.assertEquals(16, mLastPercentageShared); Assert.assertEquals(16, mLastPercentageShared);
Assert.assertEquals(7, mLastPropertiesRequested); Assert.assertEquals(15, mLastPropertiesRequested);
} }
@Test @Test
...@@ -454,7 +495,8 @@ public class ContactsPickerDialogTest ...@@ -454,7 +495,8 @@ public class ContactsPickerDialogTest
// Create a dialog showing names only. // Create a dialog showing names only.
createDialog(/* multiselect = */ false, /* includeNames = */ true, createDialog(/* multiselect = */ false, /* includeNames = */ true,
/* includeEmails = */ false, /* includeEmails = */ false,
/* includeTel = */ false); /* includeTel = */ false,
/* includeAddresses = */ false);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
clickCancel(); clickCancel();
Assert.assertEquals(4, mLastPropertiesRequested); Assert.assertEquals(4, mLastPropertiesRequested);
...@@ -462,7 +504,8 @@ public class ContactsPickerDialogTest ...@@ -462,7 +504,8 @@ public class ContactsPickerDialogTest
// Create a dialog showing emails only. // Create a dialog showing emails only.
createDialog(/* multiselect = */ false, /* includeNames = */ false, createDialog(/* multiselect = */ false, /* includeNames = */ false,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ false); /* includeTel = */ false,
/* includeAddresses = */ false);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
clickCancel(); clickCancel();
Assert.assertEquals(2, mLastPropertiesRequested); Assert.assertEquals(2, mLastPropertiesRequested);
...@@ -470,10 +513,20 @@ public class ContactsPickerDialogTest ...@@ -470,10 +513,20 @@ public class ContactsPickerDialogTest
// Create a dialog showing telephone numbers only. // Create a dialog showing telephone numbers only.
createDialog(/* multiselect = */ false, /* includeNames = */ false, createDialog(/* multiselect = */ false, /* includeNames = */ false,
/* includeEmails = */ false, /* includeEmails = */ false,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ false);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
clickCancel(); clickCancel();
Assert.assertEquals(1, mLastPropertiesRequested); Assert.assertEquals(1, mLastPropertiesRequested);
// Create a dialog showing addresses only.
createDialog(/* multiselect = */ false, /* includeNames = */ false,
/* includeEmails = */ false,
/* includeTel = */ false,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing());
clickCancel();
Assert.assertEquals(8, mLastPropertiesRequested);
} }
@Test @Test
...@@ -481,7 +534,8 @@ public class ContactsPickerDialogTest ...@@ -481,7 +534,8 @@ public class ContactsPickerDialogTest
public void testSelectAll() throws Throwable { public void testSelectAll() throws Throwable {
createDialog(/* multiselect = */ true, /* includeNames = */ true, createDialog(/* multiselect = */ true, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
toggleSelectAll(6, ContactsPickerAction.SELECT_ALL); toggleSelectAll(6, ContactsPickerAction.SELECT_ALL);
...@@ -510,7 +564,8 @@ public class ContactsPickerDialogTest ...@@ -510,7 +564,8 @@ public class ContactsPickerDialogTest
public void testNoSearchStringNoCrash() throws Throwable { public void testNoSearchStringNoCrash() throws Throwable {
createDialog(/* multiselect = */ true, /* includeNames = */ true, createDialog(/* multiselect = */ true, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
clickSearchButton(); clickSearchButton();
...@@ -524,7 +579,8 @@ public class ContactsPickerDialogTest ...@@ -524,7 +579,8 @@ public class ContactsPickerDialogTest
createDialog(/* multiselect = */ true, /* includeNames = */ true, createDialog(/* multiselect = */ true, /* includeNames = */ true,
/* includeEmails = */ true, /* includeEmails = */ true,
/* includeTel = */ true); /* includeTel = */ true,
/* includeAddresses = */ true);
Assert.assertTrue(mDialog.isShowing()); Assert.assertTrue(mDialog.isShowing());
dismissDialog(); dismissDialog();
......
...@@ -63,41 +63,56 @@ void ContactsProviderAndroid::Select(bool multiple, ...@@ -63,41 +63,56 @@ void ContactsProviderAndroid::Select(bool multiple,
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
Java_ContactsDialogHost_showDialog( Java_ContactsDialogHost_showDialog(
env, dialog_, multiple, include_names, include_emails, include_tel, env, dialog_, multiple, include_names, include_emails, include_tel,
include_addresses,
base::android::ConvertUTF16ToJavaString(env, formatted_origin_)); base::android::ConvertUTF16ToJavaString(env, formatted_origin_));
} }
void ContactsProviderAndroid::AddContact( void ContactsProviderAndroid::AddContact(
JNIEnv* env, JNIEnv* env,
jboolean include_names,
jboolean include_emails,
jboolean include_tel,
const base::android::JavaParamRef<jobjectArray>& names_java, const base::android::JavaParamRef<jobjectArray>& names_java,
const base::android::JavaParamRef<jobjectArray>& emails_java, const base::android::JavaParamRef<jobjectArray>& emails_java,
const base::android::JavaParamRef<jobjectArray>& tel_java) { const base::android::JavaParamRef<jobjectArray>& tel_java,
const base::android::JavaParamRef<jobjectArray>& addresses_java) {
DCHECK(callback_); DCHECK(callback_);
base::Optional<std::vector<std::string>> names; base::Optional<std::vector<std::string>> names;
if (include_names) { if (names_java) {
std::vector<std::string> names_vector; std::vector<std::string> names_vector;
AppendJavaStringArrayToStringVector(env, names_java, &names_vector); AppendJavaStringArrayToStringVector(env, names_java, &names_vector);
names = names_vector; names = std::move(names_vector);
} }
base::Optional<std::vector<std::string>> emails; base::Optional<std::vector<std::string>> emails;
if (include_emails) { if (emails_java) {
std::vector<std::string> emails_vector; std::vector<std::string> emails_vector;
AppendJavaStringArrayToStringVector(env, emails_java, &emails_vector); AppendJavaStringArrayToStringVector(env, emails_java, &emails_vector);
emails = emails_vector; emails = std::move(emails_vector);
} }
base::Optional<std::vector<std::string>> tel; base::Optional<std::vector<std::string>> tel;
if (include_tel) { if (tel_java) {
std::vector<std::string> tel_vector; std::vector<std::string> tel_vector;
AppendJavaStringArrayToStringVector(env, tel_java, &tel_vector); AppendJavaStringArrayToStringVector(env, tel_java, &tel_vector);
tel = tel_vector; tel = std::move(tel_vector);
} }
base::Optional<std::vector<payments::mojom::PaymentAddressPtr>> addresses; base::Optional<std::vector<payments::mojom::PaymentAddressPtr>> addresses;
if (addresses_java) {
std::vector<payments::mojom::PaymentAddressPtr> addresses_vector;
for (const base::android::JavaRef<jbyteArray>& j_address :
addresses_java.ReadElements<jbyteArray>()) {
payments::mojom::PaymentAddressPtr address;
if (!payments::mojom::PaymentAddress::Deserialize(
static_cast<jbyte*>(env->GetDirectBufferAddress(j_address.obj())),
env->GetDirectBufferCapacity(j_address.obj()), &address)) {
continue;
}
addresses_vector.push_back(std::move(address));
}
addresses = std::move(addresses_vector);
}
blink::mojom::ContactInfoPtr contact = blink::mojom::ContactInfoPtr contact =
blink::mojom::ContactInfo::New(std::move(names), std::move(emails), blink::mojom::ContactInfo::New(std::move(names), std::move(emails),
......
...@@ -32,13 +32,12 @@ class ContactsProviderAndroid : public ContactsProvider { ...@@ -32,13 +32,12 @@ class ContactsProviderAndroid : public ContactsProvider {
// Adds one contact to the list of contacts selected. Note, EndContactsList // Adds one contact to the list of contacts selected. Note, EndContactsList
// (or EndWithPermissionDenied) must be called to signal the end of the // (or EndWithPermissionDenied) must be called to signal the end of the
// construction of the contacts list. // construction of the contacts list.
void AddContact(JNIEnv* env, void AddContact(
jboolean includeNames, JNIEnv* env,
jboolean includeEmails, const base::android::JavaParamRef<jobjectArray>& names_java,
jboolean includeTel, const base::android::JavaParamRef<jobjectArray>& emails_java,
const base::android::JavaParamRef<jobjectArray>& names_java, const base::android::JavaParamRef<jobjectArray>& tel_java,
const base::android::JavaParamRef<jobjectArray>& emails_java, const base::android::JavaParamRef<jobjectArray>& addresses_java);
const base::android::JavaParamRef<jobjectArray>& tel_java);
// Signals the end of adding contacts to the list. The contact list is // Signals the end of adding contacts to the list. The contact list is
// returned to the web page, the other params are logged via UKM. // returned to the web page, the other params are logged via UKM.
......
...@@ -15,6 +15,7 @@ import org.chromium.ui.ContactsPickerListener; ...@@ -15,6 +15,7 @@ import org.chromium.ui.ContactsPickerListener;
import org.chromium.ui.UiUtils; import org.chromium.ui.UiUtils;
import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid;
import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
/** /**
...@@ -44,7 +45,7 @@ public class ContactsDialogHost implements ContactsPickerListener { ...@@ -44,7 +45,7 @@ public class ContactsDialogHost implements ContactsPickerListener {
@CalledByNative @CalledByNative
private void showDialog(boolean multiple, boolean includeNames, boolean includeEmails, private void showDialog(boolean multiple, boolean includeNames, boolean includeEmails,
boolean includeTel, String formattedOrigin) { boolean includeTel, boolean includeAddresses, String formattedOrigin) {
if (mWindowAndroid.getActivity().get() == null) { if (mWindowAndroid.getActivity().get() == null) {
ContactsDialogHostJni.get().endWithPermissionDenied(mNativeContactsProviderAndroid); ContactsDialogHostJni.get().endWithPermissionDenied(mNativeContactsProviderAndroid);
return; return;
...@@ -52,7 +53,8 @@ public class ContactsDialogHost implements ContactsPickerListener { ...@@ -52,7 +53,8 @@ public class ContactsDialogHost implements ContactsPickerListener {
if (mWindowAndroid.hasPermission(Manifest.permission.READ_CONTACTS)) { if (mWindowAndroid.hasPermission(Manifest.permission.READ_CONTACTS)) {
if (!UiUtils.showContactsPicker(mWindowAndroid.getActivity().get(), this, multiple, if (!UiUtils.showContactsPicker(mWindowAndroid.getActivity().get(), this, multiple,
includeNames, includeEmails, includeTel, formattedOrigin)) { includeNames, includeEmails, includeTel, includeAddresses,
formattedOrigin)) {
ContactsDialogHostJni.get().endWithPermissionDenied(mNativeContactsProviderAndroid); ContactsDialogHostJni.get().endWithPermissionDenied(mNativeContactsProviderAndroid);
} }
return; return;
...@@ -70,7 +72,7 @@ public class ContactsDialogHost implements ContactsPickerListener { ...@@ -70,7 +72,7 @@ public class ContactsDialogHost implements ContactsPickerListener {
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) { && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (!UiUtils.showContactsPicker(mWindowAndroid.getActivity().get(), this, if (!UiUtils.showContactsPicker(mWindowAndroid.getActivity().get(), this,
multiple, includeNames, includeEmails, includeTel, multiple, includeNames, includeEmails, includeTel,
formattedOrigin)) { includeAddresses, formattedOrigin)) {
ContactsDialogHostJni.get().endWithPermissionDenied( ContactsDialogHostJni.get().endWithPermissionDenied(
mNativeContactsProviderAndroid); mNativeContactsProviderAndroid);
} }
...@@ -95,7 +97,6 @@ public class ContactsDialogHost implements ContactsPickerListener { ...@@ -95,7 +97,6 @@ public class ContactsDialogHost implements ContactsPickerListener {
case ContactsPickerAction.CONTACTS_SELECTED: case ContactsPickerAction.CONTACTS_SELECTED:
for (Contact contact : contacts) { for (Contact contact : contacts) {
ContactsDialogHostJni.get().addContact(mNativeContactsProviderAndroid, ContactsDialogHostJni.get().addContact(mNativeContactsProviderAndroid,
contact.names != null, contact.emails != null, contact.tel != null,
contact.names != null contact.names != null
? contact.names.toArray(new String[contact.names.size()]) ? contact.names.toArray(new String[contact.names.size()])
: null, : null,
...@@ -104,6 +105,10 @@ public class ContactsDialogHost implements ContactsPickerListener { ...@@ -104,6 +105,10 @@ public class ContactsDialogHost implements ContactsPickerListener {
: null, : null,
contact.tel != null contact.tel != null
? contact.tel.toArray(new String[contact.tel.size()]) ? contact.tel.toArray(new String[contact.tel.size()])
: null,
contact.serializedAddresses != null
? contact.serializedAddresses.toArray(
new ByteBuffer[contact.serializedAddresses.size()])
: null); : null);
} }
ContactsDialogHostJni.get().endContactsList( ContactsDialogHostJni.get().endContactsList(
...@@ -118,9 +123,8 @@ public class ContactsDialogHost implements ContactsPickerListener { ...@@ -118,9 +123,8 @@ public class ContactsDialogHost implements ContactsPickerListener {
@NativeMethods @NativeMethods
interface Natives { interface Natives {
void addContact(long nativeContactsProviderAndroid, boolean includeNames, void addContact(long nativeContactsProviderAndroid, String[] names, String[] emails,
boolean includeEmails, boolean includeTel, String[] names, String[] emails, String[] tel, ByteBuffer[] addresses);
String[] tel);
void endContactsList( void endContactsList(
long nativeContactsProviderAndroid, int percentageShared, int propertiesRequested); long nativeContactsProviderAndroid, int percentageShared, int propertiesRequested);
void endWithPermissionDenied(long nativeContactsProviderAndroid); void endWithPermissionDenied(long nativeContactsProviderAndroid);
......
...@@ -17,7 +17,8 @@ enum ContactsPickerPropertiesRequested { ...@@ -17,7 +17,8 @@ enum ContactsPickerPropertiesRequested {
PROPERTIES_TELS = 1 << 0, PROPERTIES_TELS = 1 << 0,
PROPERTIES_EMAILS = 1 << 1, PROPERTIES_EMAILS = 1 << 1,
PROPERTIES_NAMES = 1 << 2, PROPERTIES_NAMES = 1 << 2,
PROPERTIES_BOUNDARY = 1 << 3, PROPERTIES_ADDRESSES = 1 << 3,
PROPERTIES_BOUNDARY = 1 << 4,
}; };
} // namespace content } // namespace content
......
...@@ -218,6 +218,7 @@ android_library("ui_utils_java") { ...@@ -218,6 +218,7 @@ android_library("ui_utils_java") {
] ]
deps = [ deps = [
"//base:base_java", "//base:base_java",
"//components/payments/mojom:mojom_java",
"//third_party/android_deps:android_support_v7_appcompat_java", "//third_party/android_deps:android_support_v7_appcompat_java",
] ]
} }
......
...@@ -6,8 +6,12 @@ package org.chromium.ui; ...@@ -6,8 +6,12 @@ package org.chromium.ui;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import org.chromium.payments.mojom.PaymentAddress;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
...@@ -15,18 +19,28 @@ import java.util.List; ...@@ -15,18 +19,28 @@ import java.util.List;
*/ */
public interface ContactsPickerListener { public interface ContactsPickerListener {
/** /**
* A container class for exhcanging contact details. * A container class for exchanging contact details.
*/ */
public class Contact { public static class Contact {
public final List<String> names; public final List<String> names;
public final List<String> emails; public final List<String> emails;
public final List<String> tel; public final List<String> tel;
public final List<ByteBuffer> serializedAddresses;
public Contact( public Contact(List<String> contactNames, List<String> contactEmails,
List<String> contactNames, List<String> contactEmails, List<String> contactTel) { List<String> contactTel, List<PaymentAddress> contactAddresses) {
names = contactNames; names = contactNames;
emails = contactEmails; emails = contactEmails;
tel = contactTel; tel = contactTel;
if (contactAddresses != null) {
serializedAddresses = new ArrayList<ByteBuffer>();
for (PaymentAddress address : contactAddresses) {
serializedAddresses.add(address.serialize());
}
} else {
serializedAddresses = null;
}
} }
} }
......
...@@ -98,12 +98,13 @@ public class UiUtils { ...@@ -98,12 +98,13 @@ public class UiUtils {
* @param includeNames Whether to include names of the contacts shared. * @param includeNames Whether to include names of the contacts shared.
* @param includeEmails Whether to include emails of the contacts shared. * @param includeEmails Whether to include emails of the contacts shared.
* @param includeTel Whether to include telephone numbers of the contacts shared. * @param includeTel Whether to include telephone numbers of the contacts shared.
* @param includeAddresses Whether to include addresses of the contacts shared.
* @param formattedOrigin The origin the data will be shared with, formatted for display * @param formattedOrigin The origin the data will be shared with, formatted for display
* with the scheme omitted. * with the scheme omitted.
*/ */
void showContactsPicker(Context context, ContactsPickerListener listener, void showContactsPicker(Context context, ContactsPickerListener listener,
boolean allowMultiple, boolean includeNames, boolean includeEmails, boolean allowMultiple, boolean includeNames, boolean includeEmails,
boolean includeTel, String formattedOrigin); boolean includeTel, boolean includeAddresses, String formattedOrigin);
/** /**
* Called when the contacts picker dialog has been dismissed. * Called when the contacts picker dialog has been dismissed.
...@@ -156,14 +157,15 @@ public class UiUtils { ...@@ -156,14 +157,15 @@ public class UiUtils {
* @param includeNames Whether to include names in the contact data returned. * @param includeNames Whether to include names in the contact data returned.
* @param includeEmails Whether to include emails in the contact data returned. * @param includeEmails Whether to include emails in the contact data returned.
* @param includeTel Whether to include telephone numbers in the contact data returned. * @param includeTel Whether to include telephone numbers in the contact data returned.
* @param includeAddresses Whether to include addresses of the contacts shared.
* @param formattedOrigin The origin the data will be shared with. * @param formattedOrigin The origin the data will be shared with.
*/ */
public static boolean showContactsPicker(Context context, ContactsPickerListener listener, public static boolean showContactsPicker(Context context, ContactsPickerListener listener,
boolean allowMultiple, boolean includeNames, boolean includeEmails, boolean includeTel, boolean allowMultiple, boolean includeNames, boolean includeEmails, boolean includeTel,
String formattedOrigin) { boolean includeAddresses, String formattedOrigin) {
if (sContactsPickerDelegate == null) return false; if (sContactsPickerDelegate == null) return false;
sContactsPickerDelegate.showContactsPicker(context, listener, allowMultiple, includeNames, sContactsPickerDelegate.showContactsPicker(context, listener, allowMultiple, includeNames,
includeEmails, includeTel, formattedOrigin); includeEmails, includeTel, includeAddresses, formattedOrigin);
return true; return true;
} }
......
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