Commit 8e9bfa17 authored by Kyle Milka's avatar Kyle Milka Committed by Commit Bot

[SharingHub] Wire up STTS to the sharing hub.

Wire up the send-tab-to-self feature to the sharing hub. This requires
some refactoring of the STTS code so that it's no longer dependent on
being passed a ChromeActivity.

Bug: 1009124
Change-Id: I7b0c0c9e4015d78d8727e6305324c663c4081095
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1925088Reviewed-by: default avatarJeffrey Cohen <jeffreycohen@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Commit-Queue: Kyle Milka <kmilka@chromium.org>
Cr-Commit-Position: refs/heads/master@{#721621}
parent 3c254f29
......@@ -420,8 +420,8 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
this, getStatusBarColorController().getStatusBarScrimDelegate(), coordinator);
initializeBottomSheetController();
mShareDelegate = new ShareDelegateImpl(
mBottomSheetController, new ShareDelegateImpl.ShareSheetDelegate());
mShareDelegate = new ShareDelegateImpl(mBottomSheetController, getActivityTabProvider(),
new ShareDelegateImpl.ShareSheetDelegate());
mShareDelegateSupplier.set(mShareDelegate);
Intent intent = getIntent();
......
......@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.send_tab_to_self;
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
......@@ -15,11 +16,10 @@ import android.widget.TextView;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareClickResult;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabImpl;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContent;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
import org.chromium.content_public.browser.NavigationEntry;
import org.chromium.ui.widget.Toast;
......@@ -28,16 +28,20 @@ import org.chromium.ui.widget.Toast;
* chosen to share it with themselves through the SendTabToSelfFeature.
*/
public class DevicePickerBottomSheetContent implements BottomSheetContent, OnItemClickListener {
private ChromeActivity mActivity;
private final Context mContext;
private final BottomSheetController mController;
private ViewGroup mToolbarView;
private ViewGroup mContentView;
private DevicePickerBottomSheetAdapter mAdapter;
private NavigationEntry mEntry;
public DevicePickerBottomSheetContent(ChromeActivity activity, NavigationEntry entry) {
mActivity = activity;
mAdapter = new DevicePickerBottomSheetAdapter(
((TabImpl) activity.getActivityTabProvider().get()).getProfile());
private final DevicePickerBottomSheetAdapter mAdapter;
private final NavigationEntry mEntry;
private final Profile mProfile;
public DevicePickerBottomSheetContent(
Context context, NavigationEntry entry, BottomSheetController controller) {
mContext = context;
mController = controller;
mProfile = Profile.getLastUsedProfile().getOriginalProfile();
mAdapter = new DevicePickerBottomSheetAdapter(mProfile);
mEntry = entry;
createToolbarView();
......@@ -52,14 +56,14 @@ public class DevicePickerBottomSheetContent implements BottomSheetContent, OnIte
}
private void createToolbarView() {
mToolbarView = (ViewGroup) LayoutInflater.from(mActivity).inflate(
mToolbarView = (ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.send_tab_to_self_device_picker_toolbar, null);
TextView toolbarText = mToolbarView.findViewById(R.id.device_picker_toolbar);
toolbarText.setText(R.string.send_tab_to_self_sheet_toolbar);
}
private void createContentView() {
mContentView = (ViewGroup) LayoutInflater.from(mActivity).inflate(
mContentView = (ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.send_tab_to_self_device_picker_list, null);
ListView listView = mContentView.findViewById(R.id.device_picker_list);
......@@ -136,15 +140,14 @@ public class DevicePickerBottomSheetContent implements BottomSheetContent, OnIte
SendTabToSelfShareClickResult.ClickType.CLICK_ITEM);
TargetDeviceInfo targetDeviceInfo = mAdapter.getItem(position);
Tab tab = mActivity.getActivityTabProvider().get();
SendTabToSelfAndroidBridge.addEntry(((TabImpl) tab).getProfile(), mEntry.getUrl(),
mEntry.getTitle(), mEntry.getTimestamp(), targetDeviceInfo.cacheGuid);
SendTabToSelfAndroidBridge.addEntry(mProfile, mEntry.getUrl(), mEntry.getTitle(),
mEntry.getTimestamp(), targetDeviceInfo.cacheGuid);
Resources res = mActivity.getResources();
Resources res = mContext.getResources();
String toastMessage =
res.getString(R.string.send_tab_to_self_toast, targetDeviceInfo.deviceName);
Toast.makeText(mActivity, toastMessage, Toast.LENGTH_SHORT).show();
Toast.makeText(mContext, toastMessage, Toast.LENGTH_SHORT).show();
mActivity.getBottomSheetController().hideContent(this, true);
mController.hideContent(this, true);
}
}
......@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.send_tab_to_self;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import org.chromium.chrome.browser.ChromeActivity;
......@@ -11,34 +13,43 @@ import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTab
import org.chromium.chrome.browser.share.ShareActivity;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContent;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
import org.chromium.content_public.browser.NavigationEntry;
/**
* A simple activity that allows Chrome to expose send tab to self as an option in the share menu.
*/
public class SendTabToSelfShareActivity extends ShareActivity {
private static BottomSheetContent sBottomSheetContentForTesting;
@Override
protected void handleShareAction(ChromeActivity triggeringActivity) {
Tab tab = triggeringActivity.getActivityTabProvider().get();
if (tab == null) return;
NavigationEntry entry = tab.getWebContents().getNavigationController().getVisibleEntry();
if (entry == null || triggeringActivity.getBottomSheetController() == null) {
actionHandler(triggeringActivity, entry, triggeringActivity.getBottomSheetController());
}
public static void actionHandler(
Context context, NavigationEntry entry, BottomSheetController controller) {
if (entry == null || controller == null) {
return;
}
SendTabToSelfShareClickResult.recordClickResult(
SendTabToSelfShareClickResult.ClickType.SHOW_DEVICE_LIST);
triggeringActivity.getBottomSheetController().requestShowContent(
createBottomSheetContent(triggeringActivity, entry), true);
controller.requestShowContent(createBottomSheetContent(context, entry, controller), true);
// TODO(crbug.com/968246): Remove the need to call this explicitly and instead have it
// automatically show since PeekStateEnabled is set to false.
triggeringActivity.getBottomSheetController().expandSheet();
controller.expandSheet();
}
@VisibleForTesting
BottomSheetContent createBottomSheetContent(ChromeActivity activity, NavigationEntry entry) {
return new DevicePickerBottomSheetContent(activity, entry);
static BottomSheetContent createBottomSheetContent(
Context context, NavigationEntry entry, BottomSheetController controller) {
if (sBottomSheetContentForTesting != null) {
return sBottomSheetContentForTesting;
}
return new DevicePickerBottomSheetContent(context, entry, controller);
}
public static boolean featureIsAvailable(Tab currentTab) {
......@@ -50,4 +61,9 @@ public class SendTabToSelfShareActivity extends ShareActivity {
}
return shouldShow;
}
@VisibleForTesting
public static void setBottomSheetContentForTesting(BottomSheetContent bottomSheetContent) {
sBottomSheetContentForTesting = bottomSheetContent;
}
}
......@@ -13,6 +13,7 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.base.Callback;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.feature_engagement.ScreenshotTabObserver;
import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
......@@ -41,20 +42,23 @@ public class ShareDelegateImpl implements ShareDelegate {
private final ShareSheetDelegate mDelegate;
static final String CANONICAL_URL_RESULT_HISTOGRAM = "Mobile.CanonicalURLResult";
private static boolean sScreenshotCaptureSkippedForTesting;
private ActivityTabProvider mActivityTabProvider;
/**
* Construct a new {@link ShareDelegateImpl}.
* @param controller The BottomSheetController for the current activity.
*/
public ShareDelegateImpl(BottomSheetController controller, ShareSheetDelegate delegate) {
public ShareDelegateImpl(BottomSheetController controller, ActivityTabProvider tabProvider,
ShareSheetDelegate delegate) {
mBottomSheetController = controller;
mDelegate = delegate;
mActivityTabProvider = tabProvider;
}
// ShareDelegate implementation.
@Override
public void share(ShareParams params) {
mDelegate.share(params, mBottomSheetController);
mDelegate.share(params, mBottomSheetController, mActivityTabProvider);
}
// ShareDelegate implementation.
......@@ -108,7 +112,7 @@ public class ShareDelegateImpl implements ShareDelegate {
OfflinePageUtils.maybeShareOfflinePage(currentTab, (ShareParams p) -> {
if (p != null) {
mDelegate.share(p, mBottomSheetController);
mDelegate.share(p, mBottomSheetController, mActivityTabProvider);
} else {
WindowAndroid window = currentTab.getWindowAndroid();
// Could not share as an offline page.
......@@ -147,7 +151,7 @@ public class ShareDelegateImpl implements ShareDelegate {
.setShareDirectly(shareDirectly)
.setSaveLastUsed(!shareDirectly)
.setScreenshotUri(blockingUri);
mDelegate.share(builder.build(), mBottomSheetController);
mDelegate.share(builder.build(), mBottomSheetController, mActivityTabProvider);
if (shareDirectly) {
RecordUserAction.record("MobileMenuDirectShare");
} else {
......@@ -240,11 +244,13 @@ public class ShareDelegateImpl implements ShareDelegate {
/**
* Trigger the share action for the specified params.
*/
void share(ShareParams params, BottomSheetController controller) {
void share(ShareParams params, BottomSheetController controller,
ActivityTabProvider tabProvider) {
if (params.shareDirectly()) {
ShareHelper.shareDirectly(params);
} else if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARING_HUB)) {
ShareSheetCoordinator coordinator = new ShareSheetCoordinator(controller);
ShareSheetCoordinator coordinator =
new ShareSheetCoordinator(controller, tabProvider);
// TODO(crbug/1009124): open custom share sheet.
coordinator.showShareSheet(params);
} else if (ShareHelper.TargetChosenReceiver.isSupported()) {
......
......@@ -14,6 +14,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfShareActivity;
import org.chromium.chrome.browser.share.qrcode.QrCodeCoordinator;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
......@@ -29,9 +31,14 @@ public class ShareSheetCoordinator {
private static final int SHARE_SHEET_ITEM = 0;
private final BottomSheetController mBottomSheetController;
private final ActivityTabProvider mActivityTabProvider;
public ShareSheetCoordinator(BottomSheetController controller) {
/**
* Constructs a new ShareSheetCoordinator.
*/
public ShareSheetCoordinator(BottomSheetController controller, ActivityTabProvider provider) {
mBottomSheetController = controller;
mActivityTabProvider = provider;
}
protected void showShareSheet(ShareParams params) {
......@@ -53,8 +60,30 @@ public class ShareSheetCoordinator {
})
.build();
// Send Tab To Self
PropertyModel sttsPropertyModel =
new PropertyModel.Builder(ShareSheetItemViewProperties.ALL_KEYS)
.with(ShareSheetItemViewProperties.ICON,
AppCompatResources.getDrawable(context, R.drawable.ic_launcher))
.with(ShareSheetItemViewProperties.LABEL,
context.getResources().getString(
R.string.send_tab_to_self_share_activity_title))
.with(ShareSheetItemViewProperties.CLICK_LISTENER,
(shareParams) -> {
mBottomSheetController.hideContent(bottomSheet, true);
SendTabToSelfShareActivity.actionHandler(
params.getWindow().getContext().get(),
mActivityTabProvider.get()
.getWebContents()
.getNavigationController()
.getVisibleEntry(),
mBottomSheetController);
})
.build();
ModelList modelList = new ModelList();
modelList.add(new ListItem(SHARE_SHEET_ITEM, qrcodePropertyModel));
modelList.add(new ListItem(SHARE_SHEET_ITEM, sttsPropertyModel));
SimpleRecyclerViewAdapter adapter = new SimpleRecyclerViewAdapter(modelList);
RecyclerView rcView =
bottomSheet.getContentView().findViewById(R.id.share_sheet_chrome_apps);
......
......@@ -16,6 +16,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareSheetDelegate;
......@@ -112,14 +113,15 @@ public class ShareDelegateImplIntegrationTest {
TestThreadUtils.runOnUiThreadBlocking(() -> {
ShareSheetDelegate delegate = new ShareSheetDelegate() {
@Override
void share(ShareParams params, BottomSheetController controller) {
void share(ShareParams params, BottomSheetController controller,
ActivityTabProvider tabProvider) {
paramsRef.set(params);
helper.notifyCalled();
}
};
new ShareDelegateImpl(
mActivityTestRule.getActivity().getBottomSheetController(), delegate)
new ShareDelegateImpl(mActivityTestRule.getActivity().getBottomSheetController(),
mActivityTestRule.getActivity().getActivityTabProvider(), delegate)
.share(mActivityTestRule.getActivity().getActivityTab(), false);
});
helper.waitForCallback(0);
......
......@@ -62,14 +62,6 @@ public class SendTabToSelfShareActivityTest {
private Profile mProfile;
private class SendTabToSelfShareActivityForTest extends SendTabToSelfShareActivity {
@Override
BottomSheetContent createBottomSheetContent(
ChromeActivity activity, NavigationEntry entry) {
return mBottomSheetContent;
}
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
......@@ -109,7 +101,8 @@ public class SendTabToSelfShareActivityTest {
// Setup the mocked object chain to get the bottom controller.
when(mChromeActivity.getBottomSheetController()).thenReturn(mBottomSheetController);
SendTabToSelfShareActivityForTest shareActivity = new SendTabToSelfShareActivityForTest();
SendTabToSelfShareActivity shareActivity = new SendTabToSelfShareActivity();
SendTabToSelfShareActivity.setBottomSheetContentForTesting(mBottomSheetContent);
shareActivity.handleShareAction(mChromeActivity);
verify(mBottomSheetController).requestShowContent(any(BottomSheetContent.class), eq(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