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