Skip to content

Commit

Permalink
Contacts Picker: Implement the JNI communications for the contacts di…
Browse files Browse the repository at this point in the history
…alog.

TBR: tedchoc, kinuko
Bug: 860467
Change-Id: I4e1715d1635f4461938984b6dd49ba106762cfe7
Reviewed-on: https://chromium-review.googlesource.com/c/1411608
Commit-Queue: Finnur Thorarinsson <finnur@chromium.org>
Reviewed-by: Yusuf Ozuysal <yusufo@chromium.org>
Reviewed-by: Peter Beverloo <peter@chromium.org>
Reviewed-by: Jeff Carpenter <jeffcarp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#624755}
  • Loading branch information
Finnur Thorarinsson authored and Commit Bot committed Jan 22, 2019
1 parent 85616a7 commit d1e1e8d
Show file tree
Hide file tree
Showing 17 changed files with 380 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@
*/
public class ContactDetails implements Comparable<ContactDetails> {
// The unique id for the contact.
private String mId;
private final String mId;

// The display name for this contact.
private String mDisplayName;
private final String mDisplayName;

// The list of emails registered for this contact.
private List<String> mEmails;
private final List<String> mEmails;

// The list of phone numbers registered for this contact.
private List<String> mPhoneNumbers;
private final List<String> mPhoneNumbers;

/**
* The ContactDetails constructor.
Expand All @@ -45,18 +45,22 @@ public ContactDetails(
mId = id;
}

/**
* Accessor for the display name.
* @return The full display name.
*/
public List<String> getDisplayNames() {
return Arrays.asList(mDisplayName);
}

public List<String> getEmails() {
return mEmails;
}

public List<String> getPhoneNumbers() {
return mPhoneNumbers;
}

public String getDisplayName() {
return mDisplayName;
}

/**
* Accessor for the ID.
* @return The ID of the contact.
*/
public String getId() {
return mId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import org.chromium.chrome.R;
import org.chromium.ui.ContactsPickerListener;

import java.util.List;

/**
* UI for the contacts picker that shows on the Android platform as a result of
* &lt;input type=file accept=contacts &gt; form element.
Expand All @@ -26,15 +24,14 @@ public class ContactsPickerDialog extends AlertDialog {
* @param context The context to use.
* @param listener The listener object that gets notified when an action is taken.
* @param allowMultiple Whether the contacts picker should allow multiple items to be selected.
* @param mimeTypes A list of mime types to show in the dialog.
*/
public ContactsPickerDialog(Context context, ContactsPickerListener listener,
boolean allowMultiple, List<String> mimeTypes) {
public ContactsPickerDialog(
Context context, ContactsPickerListener listener, boolean allowMultiple) {
super(context, R.style.FullscreenWhite);

// Initialize the main content view.
mCategoryView = new PickerCategoryView(context, allowMultiple);
mCategoryView.initialize(this, listener, mimeTypes);
mCategoryView.initialize(this, listener);
setView(mCategoryView);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ public class PickerCategoryView extends RelativeLayout
// Whether the picker is in multi-selection mode.
private boolean mMultiSelectionAllowed;

// The MIME types requested.
private List<String> mMimeTypes;

/**
* @param multiSelectionAllowed Whether the contacts picker should allow multiple items to be
* selected.
Expand Down Expand Up @@ -157,18 +154,15 @@ public PickerCategoryView(Context context, boolean multiSelectionAllowed) {
* Initializes the PickerCategoryView object.
* @param dialog The dialog showing us.
* @param listener The listener who should be notified of actions.
* @param mimeTypes A list of mime types to show in the dialog.
*/
public void initialize(
ContactsPickerDialog dialog, ContactsPickerListener listener, List<String> mimeTypes) {
public void initialize(ContactsPickerDialog dialog, ContactsPickerListener listener) {
mDialog = dialog;
mListener = listener;
mMimeTypes = new ArrayList<>(mimeTypes);

mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null);
executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null, null);
}
});

Expand Down Expand Up @@ -249,12 +243,12 @@ public void onSelectAllToggled(boolean allSelected) {
mSelectionDelegate.setSelectedItems(
new HashSet<ContactDetails>(mPickerAdapter.getAllContacts()));
mListener.onContactsPickerUserAction(
ContactsPickerListener.ContactsPickerAction.SELECT_ALL, null);
ContactsPickerListener.ContactsPickerAction.SELECT_ALL, null, null);
} else {
mSelectionDelegate.setSelectedItems(new HashSet<ContactDetails>());
mPreviousSelection = null;
mListener.onContactsPickerUserAction(
ContactsPickerListener.ContactsPickerAction.UNDO_SELECT_ALL, null);
ContactsPickerListener.ContactsPickerAction.UNDO_SELECT_ALL, null, null);
}
}

Expand All @@ -268,7 +262,7 @@ public void onClick(View view) {
} else if (id == R.id.search) {
onStartSearch();
} else {
executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null);
executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null, null);
}
}

Expand Down Expand Up @@ -307,18 +301,22 @@ private void notifyContactsSelected() {

StringWriter out = new StringWriter();
final JsonWriter writer = new JsonWriter(out);
List<ContactsPickerListener.Contact> contacts =
new ArrayList<ContactsPickerListener.Contact>();

try {
writer.beginArray();
for (ContactDetails contactDetails : selectedContacts) {
contactDetails.appendJson(writer);
contacts.add(new ContactsPickerListener.Contact(contactDetails.getDisplayNames(),
contactDetails.getEmails(), contactDetails.getPhoneNumbers()));
}
writer.endArray();
executeAction(
ContactsPickerListener.ContactsPickerAction.CONTACTS_SELECTED, out.toString());
executeAction(ContactsPickerListener.ContactsPickerAction.CONTACTS_SELECTED,
out.toString(), contacts);
} catch (IOException e) {
assert false;
executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null);
executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null, null);
}
}

Expand All @@ -327,9 +325,9 @@ private void notifyContactsSelected() {
* @param action The action taken.
* @param contacts The contacts that were selected (if any).
*/
private void executeAction(
@ContactsPickerListener.ContactsPickerAction int action, String contacts) {
mListener.onContactsPickerUserAction(action, contacts);
private void executeAction(@ContactsPickerListener.ContactsPickerAction int action,
String contactsJson, List<ContactsPickerListener.Contact> contacts) {
mListener.onContactsPickerUserAction(action, contactsJson, contacts);
mDialog.dismiss();
UiUtils.onContactsPickerDismissed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ public void onPhotoPickerDismissed() {
private ContactsPickerDialog mDialog;

@Override
public void showContactsPicker(Context context, ContactsPickerListener listener,
boolean allowMultiple, List<String> mimeTypes) {
mDialog = new ContactsPickerDialog(context, listener, allowMultiple, mimeTypes);
public void showContactsPicker(
Context context, ContactsPickerListener listener, boolean allowMultiple) {
mDialog = new ContactsPickerDialog(context, listener, allowMultiple);
mDialog.getWindow().getAttributes().windowAnimations =
R.style.PickerDialogAnimation;
mDialog.show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;

Expand Down Expand Up @@ -101,9 +100,10 @@ public void setUp() throws Exception {
// ContactsPickerDialog.ContactsPickerListener:

@Override
public void onContactsPickerUserAction(@ContactsPickerAction int action, String contacts) {
public void onContactsPickerUserAction(@ContactsPickerAction int action, String contactsJson,
List<ContactsPickerListener.Contact> contacts) {
mLastActionRecorded = action;
mLastSelectedContacts = contacts;
mLastSelectedContacts = contactsJson;
onActionCallback.notifyCalled();
}

Expand All @@ -119,15 +119,14 @@ private RecyclerView getRecyclerView() {
return (RecyclerView) mDialog.findViewById(R.id.recycler_view);
}

private ContactsPickerDialog createDialog(
final boolean multiselect, final List<String> mimeTypes) throws Exception {
private ContactsPickerDialog createDialog(final boolean multiselect) throws Exception {
final ContactsPickerDialog dialog =
ThreadUtils.runOnUiThreadBlocking(new Callable<ContactsPickerDialog>() {
@Override
public ContactsPickerDialog call() {
final ContactsPickerDialog dialog =
new ContactsPickerDialog(mActivityTestRule.getActivity(),
ContactsPickerDialogTest.this, multiselect, mimeTypes);
ContactsPickerDialogTest.this, multiselect);
dialog.show();
return dialog;
}
Expand Down Expand Up @@ -239,7 +238,7 @@ private void addContact(JsonWriter writer, String displayName) throws Throwable
@Test
@LargeTest
public void testNoSelection() throws Throwable {
createDialog(/* multiselect = */ false, Arrays.asList("image/*"));
createDialog(/* multiselect = */ false);
Assert.assertTrue(mDialog.isShowing());

int expectedSelectionCount = 1;
Expand All @@ -255,7 +254,7 @@ public void testNoSelection() throws Throwable {
@Test
@LargeTest
public void testSingleSelectionContacts() throws Throwable {
createDialog(/* multiselect = */ false, Arrays.asList("image/*"));
createDialog(/* multiselect = */ false);
Assert.assertTrue(mDialog.isShowing());

// Expected selection count is 1 because clicking on a new view deselects other.
Expand All @@ -279,7 +278,7 @@ public void testSingleSelectionContacts() throws Throwable {
@Test
@LargeTest
public void testMultiSelectionContacts() throws Throwable {
createDialog(/* multiselect = */ true, Arrays.asList("image/*"));
createDialog(/* multiselect = */ true);
Assert.assertTrue(mDialog.isShowing());

// Multi-selection is enabled, so each click is counted.
Expand All @@ -306,7 +305,7 @@ public void testMultiSelectionContacts() throws Throwable {
@Test
@LargeTest
public void testSelectAll() throws Throwable {
createDialog(/* multiselect = */ true, Arrays.asList("image/*"));
createDialog(/* multiselect = */ true);
Assert.assertTrue(mDialog.isShowing());

toggleSelectAll(6, ContactsPickerAction.SELECT_ALL);
Expand All @@ -333,7 +332,7 @@ public void testSelectAll() throws Throwable {
@Test
@LargeTest
public void testNoSearchStringNoCrash() throws Throwable {
createDialog(/* multiselect = */ true, Arrays.asList("image/*"));
createDialog(/* multiselect = */ true);
Assert.assertTrue(mDialog.isShowing());

clickSearchButton();
Expand Down
3 changes: 3 additions & 0 deletions content/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ jumbo_source_set("browser") {
"code_cache/generated_code_cache_context.h",
"contacts/contacts_manager_impl.cc",
"contacts/contacts_manager_impl.h",
"contacts/contacts_provider.h",
"startup_data_impl.cc",
"startup_data_impl.h",
"startup_helper.cc",
Expand Down Expand Up @@ -2281,6 +2282,8 @@ jumbo_source_set("browser") {
"android/tracing_controller_android.h",
"android/web_contents_observer_proxy.cc",
"android/web_contents_observer_proxy.h",
"contacts/contacts_provider_android.cc",
"contacts/contacts_provider_android.h",
"font_unique_name_lookup/font_unique_name_lookup.cc",
"font_unique_name_lookup/font_unique_name_lookup.h",
"font_unique_name_lookup/font_unique_name_lookup_service.cc",
Expand Down
38 changes: 32 additions & 6 deletions content/browser/contacts/contacts_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,51 @@
#include <vector>

#include "base/callback.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/strong_binding.h"

#if defined(OS_ANDROID)
#include "content/browser/contacts/contacts_provider_android.h"
#endif

namespace content {

namespace {

std::unique_ptr<ContactsProvider> CreateProvider(
RenderFrameHostImpl* render_frame_host) {
#if defined(OS_ANDROID)
return std::make_unique<ContactsProviderAndroid>(render_frame_host);
#else
return nullptr;
#endif
}

} // namespace

// static
void ContactsManagerImpl::Create(blink::mojom::ContactsManagerRequest request) {
mojo::MakeStrongBinding(std::make_unique<ContactsManagerImpl>(),
std::move(request));
void ContactsManagerImpl::Create(RenderFrameHostImpl* render_frame_host,
blink::mojom::ContactsManagerRequest request) {
mojo::MakeStrongBinding(
std::make_unique<ContactsManagerImpl>(render_frame_host),
std::move(request));
}

ContactsManagerImpl::ContactsManagerImpl() = default;
ContactsManagerImpl::ContactsManagerImpl(RenderFrameHostImpl* render_frame_host)
: contacts_provider_(CreateProvider(render_frame_host)) {}

ContactsManagerImpl::~ContactsManagerImpl() = default;

void ContactsManagerImpl::Select(bool multiple,
bool include_names,
bool include_emails,
SelectCallback callback) {
// TODO(finnur): Implement showing the dialog instead of returning null.
std::move(callback).Run(base::nullopt);
if (contacts_provider_) {
contacts_provider_->Select(multiple, include_names, include_emails,
std::move(callback));
} else {
std::move(callback).Run(base::nullopt);
}
}

} // namespace content
10 changes: 8 additions & 2 deletions content/browser/contacts/contacts_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
#ifndef CONTENT_BROWSER_CONTACTS_CONTACTS_MANAGER_IMPL_H_
#define CONTENT_BROWSER_CONTACTS_CONTACTS_MANAGER_IMPL_H_

#include "content/browser/contacts/contacts_provider.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/mojom/contacts/contacts_manager.mojom.h"

namespace content {

class RenderFrameHostImpl;

class CONTENT_EXPORT ContactsManagerImpl
: public blink::mojom::ContactsManager {
public:
static void Create(blink::mojom::ContactsManagerRequest request);
static void Create(RenderFrameHostImpl* render_frame_host,
blink::mojom::ContactsManagerRequest request);

ContactsManagerImpl();
explicit ContactsManagerImpl(RenderFrameHostImpl* render_frame_host);
~ContactsManagerImpl() override;

void Select(bool multiple,
Expand All @@ -24,6 +28,8 @@ class CONTENT_EXPORT ContactsManagerImpl
SelectCallback callback) override;

private:
std::unique_ptr<ContactsProvider> contacts_provider_;

DISALLOW_COPY_AND_ASSIGN(ContactsManagerImpl);
};

Expand Down
Loading

0 comments on commit d1e1e8d

Please sign in to comment.