Fetch user avatars for collaboration messages.
Bug: 374806190 Change-Id: Ib45785ca7208a7b295de0f953d644faabb674ee5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020330 Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Siddhartha S <ssid@chromium.org> Reviewed-by: Calder Kitagawa <ckitagawa@chromium.org> Commit-Queue: Siddhartha S <ssid@chromium.org> Cr-Commit-Position: refs/heads/main@{#1383287}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
4e72956d07
commit
f6b02b90d9
chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing
components
collaboration
public
data_sharing
public
android
java
src
org
chromium
components
data_sharing
@ -6,6 +6,8 @@ package org.chromium.chrome.browser.data_sharing;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
@ -14,6 +16,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.chromium.base.Callback;
|
||||
import org.chromium.base.CallbackUtils;
|
||||
import org.chromium.base.Token;
|
||||
import org.chromium.base.supplier.Supplier;
|
||||
import org.chromium.chrome.browser.collaboration.messaging.MessagingBackendServiceFactory;
|
||||
@ -27,6 +30,10 @@ import org.chromium.components.collaboration.messaging.InstantNotificationLevel;
|
||||
import org.chromium.components.collaboration.messaging.MessageUtils;
|
||||
import org.chromium.components.collaboration.messaging.MessagingBackendService;
|
||||
import org.chromium.components.collaboration.messaging.MessagingBackendService.InstantMessageDelegate;
|
||||
import org.chromium.components.data_sharing.DataSharingUIDelegate;
|
||||
import org.chromium.components.data_sharing.GroupMember;
|
||||
import org.chromium.components.data_sharing.configs.DataSharingAvatarBitmapConfig;
|
||||
import org.chromium.components.data_sharing.configs.DataSharingAvatarBitmapConfig.DataSharingAvatarCallback;
|
||||
import org.chromium.components.messages.MessageBannerProperties;
|
||||
import org.chromium.components.messages.MessageDispatcher;
|
||||
import org.chromium.components.messages.MessageDispatcherProvider;
|
||||
@ -34,6 +41,7 @@ import org.chromium.components.messages.MessageIdentifier;
|
||||
import org.chromium.components.messages.PrimaryActionClickBehavior;
|
||||
import org.chromium.ui.base.WindowAndroid;
|
||||
import org.chromium.ui.modelutil.PropertyModel;
|
||||
import org.chromium.ui.util.ColorUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -63,6 +71,7 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
}
|
||||
|
||||
private final List<AttachedWindowInfo> mAttachList = new ArrayList<>();
|
||||
private final DataSharingUIDelegate mDataSharingUiDelegate;
|
||||
|
||||
/**
|
||||
* @param profile The current profile to get dependencies with.
|
||||
@ -72,6 +81,7 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
MessagingBackendService messagingBackendService =
|
||||
MessagingBackendServiceFactory.getForProfile(profile);
|
||||
messagingBackendService.setInstantMessageDelegate(this);
|
||||
mDataSharingUiDelegate = DataSharingServiceFactory.getForProfile(profile).getUiDelegate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,9 +201,21 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Drawable iconFromMessage(Context context) {
|
||||
// TODO(https://crbug.com/369163940): Fetch this, potentially async.
|
||||
return ContextCompat.getDrawable(context, R.drawable.ic_features_24dp);
|
||||
private void fetchAvatarIconFromMessage(
|
||||
Context context, GroupMember groupMember, Callback<Drawable> onDrawable) {
|
||||
DataSharingAvatarCallback onBitmap =
|
||||
(Bitmap bitmap) -> onDrawable.onResult(new BitmapDrawable(bitmap));
|
||||
int sizeInPixels =
|
||||
context.getResources().getDimensionPixelSize(R.dimen.message_description_icon_size);
|
||||
DataSharingAvatarBitmapConfig config =
|
||||
new DataSharingAvatarBitmapConfig.Builder()
|
||||
.setContext(context)
|
||||
.setGroupMember(groupMember)
|
||||
.setIsDarkMode(ColorUtils.inNightMode(context))
|
||||
.setAvatarSizeInPixels(sizeInPixels)
|
||||
.setDataSharingAvatarCallback(onBitmap)
|
||||
.build();
|
||||
mDataSharingUiDelegate.getAvatarBitmap(config);
|
||||
}
|
||||
|
||||
private void showTabRemoved(
|
||||
@ -207,16 +229,23 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
context.getString(
|
||||
R.string.data_sharing_browser_message_removed_tab, givenName, tabTitle);
|
||||
String buttonText = context.getString(R.string.data_sharing_browser_message_reopen);
|
||||
Drawable icon = iconFromMessage(context);
|
||||
GroupMember groupMember = MessageUtils.extractMember(message);
|
||||
// TODO(https://crbug.com/369163940): Once the message has the url, we can restore.
|
||||
showGenericMessage(
|
||||
messageDispatcher,
|
||||
MessageIdentifier.TAB_REMOVED_THROUGH_COLLABORATION,
|
||||
title,
|
||||
buttonText,
|
||||
icon,
|
||||
() -> {},
|
||||
onSuccess);
|
||||
Runnable action = CallbackUtils.emptyRunnable();
|
||||
|
||||
fetchAvatarIconFromMessage(
|
||||
context,
|
||||
groupMember,
|
||||
(icon) -> {
|
||||
showGenericMessage(
|
||||
messageDispatcher,
|
||||
MessageIdentifier.TAB_REMOVED_THROUGH_COLLABORATION,
|
||||
title,
|
||||
buttonText,
|
||||
icon,
|
||||
action,
|
||||
onSuccess);
|
||||
});
|
||||
}
|
||||
|
||||
private void showTabChange(
|
||||
@ -230,16 +259,23 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
context.getString(
|
||||
R.string.data_sharing_browser_message_changed_tab, givenName, tabTitle);
|
||||
String buttonText = context.getString(R.string.data_sharing_browser_message_reopen);
|
||||
Drawable icon = iconFromMessage(context);
|
||||
GroupMember groupMember = MessageUtils.extractMember(message);
|
||||
// TODO(https://crbug.com/369163940): Once the message has the url, we can restore.
|
||||
showGenericMessage(
|
||||
messageDispatcher,
|
||||
MessageIdentifier.TAB_NAVIGATED_THROUGH_COLLABORATION,
|
||||
title,
|
||||
buttonText,
|
||||
icon,
|
||||
() -> {},
|
||||
onSuccess);
|
||||
Runnable action = CallbackUtils.emptyRunnable();
|
||||
|
||||
fetchAvatarIconFromMessage(
|
||||
context,
|
||||
groupMember,
|
||||
(icon) -> {
|
||||
showGenericMessage(
|
||||
messageDispatcher,
|
||||
MessageIdentifier.TAB_NAVIGATED_THROUGH_COLLABORATION,
|
||||
title,
|
||||
buttonText,
|
||||
icon,
|
||||
action,
|
||||
onSuccess);
|
||||
});
|
||||
}
|
||||
|
||||
private void showCollaborationMemberAdded(
|
||||
@ -258,7 +294,7 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
givenName,
|
||||
tabGroupTitle);
|
||||
String buttonText = activity.getString(R.string.data_sharing_browser_message_manage);
|
||||
Drawable icon = iconFromMessage(activity);
|
||||
GroupMember groupMember = MessageUtils.extractMember(message);
|
||||
Runnable openManageSharingRunnable =
|
||||
() -> {
|
||||
// TODO(crbug.com/379148260): Use shared #isCollaborationIdValid.
|
||||
@ -266,14 +302,20 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
dataSharingTabManager.showManageSharing(activity, collaborationId);
|
||||
}
|
||||
};
|
||||
showGenericMessage(
|
||||
messageDispatcher,
|
||||
MessageIdentifier.COLLABORATION_MEMBER_ADDED,
|
||||
title,
|
||||
buttonText,
|
||||
icon,
|
||||
openManageSharingRunnable,
|
||||
onSuccess);
|
||||
|
||||
fetchAvatarIconFromMessage(
|
||||
activity,
|
||||
groupMember,
|
||||
(icon) -> {
|
||||
showGenericMessage(
|
||||
messageDispatcher,
|
||||
MessageIdentifier.COLLABORATION_MEMBER_ADDED,
|
||||
title,
|
||||
buttonText,
|
||||
icon,
|
||||
openManageSharingRunnable,
|
||||
onSuccess);
|
||||
});
|
||||
}
|
||||
|
||||
private void showCollaborationRemoved(
|
||||
@ -294,7 +336,7 @@ public class InstantMessageDelegateImpl implements InstantMessageDelegate {
|
||||
title,
|
||||
buttonText,
|
||||
icon,
|
||||
() -> {},
|
||||
CallbackUtils.emptyRunnable(),
|
||||
onSuccess);
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import static org.chromium.components.messages.MessageBannerProperties.TITLE;
|
||||
import static org.chromium.components.messages.PrimaryActionClickBehavior.DISMISS_IMMEDIATELY;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
|
||||
@ -54,6 +55,9 @@ import org.chromium.components.collaboration.messaging.MessageAttribution;
|
||||
import org.chromium.components.collaboration.messaging.MessagingBackendService;
|
||||
import org.chromium.components.collaboration.messaging.TabGroupMessageMetadata;
|
||||
import org.chromium.components.collaboration.messaging.TabMessageMetadata;
|
||||
import org.chromium.components.data_sharing.DataSharingService;
|
||||
import org.chromium.components.data_sharing.DataSharingUIDelegate;
|
||||
import org.chromium.components.data_sharing.configs.DataSharingAvatarBitmapConfig;
|
||||
import org.chromium.components.messages.ManagedMessageDispatcher;
|
||||
import org.chromium.components.messages.MessageIdentifier;
|
||||
import org.chromium.components.messages.MessagesFactory;
|
||||
@ -81,12 +85,15 @@ public class InstantMessageDelegateImplUnitTest {
|
||||
|
||||
@Mock private Profile mProfile;
|
||||
@Mock private MessagingBackendService mMessagingBackendService;
|
||||
@Mock private DataSharingService mDataSharingService;
|
||||
@Mock private DataSharingUIDelegate mDataSharingUiDelegate;
|
||||
@Mock private ManagedMessageDispatcher mManagedMessageDispatcher;
|
||||
@Mock private WindowAndroid mWindowAndroid;
|
||||
@Mock private TabGroupModelFilter mTabGroupModelFilter;
|
||||
@Mock private Callback<Boolean> mSuccessCallback;
|
||||
@Mock private DataSharingNotificationManager mDataSharingNotificationManager;
|
||||
@Mock private DataSharingTabManager mDataSharingTabManager;
|
||||
@Mock private Bitmap mAvatarBitmap;
|
||||
|
||||
@Captor private ArgumentCaptor<PropertyModel> mPropertyModelCaptor;
|
||||
|
||||
@ -102,6 +109,13 @@ public class InstantMessageDelegateImplUnitTest {
|
||||
|
||||
private void onActivity(Activity activity) {
|
||||
MessagingBackendServiceFactory.setForTesting(mMessagingBackendService);
|
||||
DataSharingServiceFactory.setForTesting(mDataSharingService);
|
||||
when(mDataSharingService.getUiDelegate()).thenReturn(mDataSharingUiDelegate);
|
||||
MockitoHelper.doCallback(
|
||||
(DataSharingAvatarBitmapConfig config) ->
|
||||
config.getDataSharingAvatarCallback().onAvatarLoaded(mAvatarBitmap))
|
||||
.when(mDataSharingUiDelegate)
|
||||
.getAvatarBitmap(any());
|
||||
|
||||
when(mWindowAndroid.getUnownedUserDataHost()).thenReturn(mUnownedUserDataHost);
|
||||
MessagesFactory.attachMessageDispatcher(mWindowAndroid, mManagedMessageDispatcher);
|
||||
|
@ -143,6 +143,7 @@ if (is_android) {
|
||||
":java",
|
||||
"//base:base_java",
|
||||
"//base:base_junit_test_support",
|
||||
"//components/data_sharing:test_support_java",
|
||||
"//components/data_sharing/public:public_java",
|
||||
"//components/saved_tab_groups/public:java",
|
||||
"//third_party/android_deps:robolectric_all_java",
|
||||
|
@ -7,6 +7,7 @@ package org.chromium.components.collaboration.messaging;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.chromium.base.Token;
|
||||
import org.chromium.components.data_sharing.GroupMember;
|
||||
|
||||
/** Provides functions to safely read fields out of messages, performing null checks. */
|
||||
public class MessageUtils {
|
||||
@ -74,4 +75,15 @@ public class MessageUtils {
|
||||
? null
|
||||
: message.attribution.collaborationId;
|
||||
}
|
||||
|
||||
/** Returns a GroupMember associated with the message, prioritizing affected over triggering. */
|
||||
public static GroupMember extractMember(@Nullable InstantMessage message) {
|
||||
if (message == null || message.attribution == null) {
|
||||
return null;
|
||||
} else if (message.attribution.affectedUser != null) {
|
||||
return message.attribution.affectedUser;
|
||||
} else {
|
||||
return message.attribution.triggeringUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ package org.chromium.components.collaboration.messaging;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import static org.chromium.components.data_sharing.SharedGroupTestHelper.GROUP_MEMBER1;
|
||||
import static org.chromium.components.data_sharing.SharedGroupTestHelper.GROUP_MEMBER2;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@ -125,4 +128,21 @@ public class MessageUtilsUnitTest {
|
||||
|
||||
assertEquals("", MessageUtils.extractTabGroupTitle(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractMember() {
|
||||
assertEquals(null, MessageUtils.extractMember(null));
|
||||
|
||||
InstantMessage message = new InstantMessage();
|
||||
assertEquals(null, MessageUtils.extractMember(message));
|
||||
|
||||
message.attribution = new MessageAttribution();
|
||||
assertEquals(null, MessageUtils.extractMember(message));
|
||||
|
||||
message.attribution.triggeringUser = GROUP_MEMBER1;
|
||||
assertEquals(GROUP_MEMBER1, MessageUtils.extractMember(message));
|
||||
|
||||
message.attribution.affectedUser = GROUP_MEMBER2;
|
||||
assertEquals(GROUP_MEMBER2, MessageUtils.extractMember(message));
|
||||
}
|
||||
}
|
||||
|
@ -19,15 +19,15 @@ public final class DataSharingAvatarBitmapConfig {
|
||||
private final DataSharingAvatarCallback mDataSharingAvatarCallback;
|
||||
|
||||
/** Interface used to pass the result of avatar loading. */
|
||||
@FunctionalInterface
|
||||
public interface DataSharingAvatarCallback {
|
||||
|
||||
/**
|
||||
* Called when the avatar bitmap is ready.
|
||||
*
|
||||
* @param bitmap The loaded avatar bitmap. If might return null, if group member is
|
||||
* invalid.
|
||||
* @param bitmap The loaded avatar bitmap. If might return null, if group member is invalid.
|
||||
*/
|
||||
default void onAvatarLoaded(Bitmap bitmap) {}
|
||||
void onAvatarLoaded(Bitmap bitmap);
|
||||
}
|
||||
|
||||
private DataSharingAvatarBitmapConfig(Builder builder) {
|
||||
|
Reference in New Issue
Block a user