Commit 119eb5ad authored by Shakti Sahu's avatar Shakti Sahu Committed by Commit Bot

Read later : Added IPH for bookmark star icon and reading list folder

This CL adds various IPHs for the read later feature.
1 - IPH to educate user about using the bookmark button on the app
menu for saving articles to reading list.
2 - IPH to educate user about location of bookmarks in app menu.
3 - Notify IPH backend whenever read later option is selected in
context menu.
4 - Notify IPH backend whenever user navigates to the read later folder
in bookmarks.

Bug: 1139076
Change-Id: Ib81e43a9746c3493bdd6f299e6a9e117aacc472c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537390Reviewed-by: default avatarShakti Sahu <shaktisahu@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarSky Malice <skym@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Commit-Queue: Shakti Sahu <shaktisahu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829055}
parent eaa15403
......@@ -1212,6 +1212,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java",
"java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java",
"java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java",
"java/src/org/chromium/chrome/browser/read_later/ReadLaterIPHController.java",
"java/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationController.java",
"java/src/org/chromium/chrome/browser/resources/ResourceMapper.java",
"java/src/org/chromium/chrome/browser/rlz/RevenueStats.java",
......
......@@ -483,6 +483,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionToOmniboxTest.java",
"javatests/src/org/chromium/chrome/browser/query_tiles/TileMatchers.java",
"javatests/src/org/chromium/chrome/browser/query_tiles/ViewActions.java",
"javatests/src/org/chromium/chrome/browser/read_later/ReadLaterIphTest.java",
"javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java",
"javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java",
......
......@@ -1656,6 +1656,7 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
Supplier<TabDelegateFactory> tabDelegateFactorySupplier = () -> {
return new TabbedModeTabDelegateFactory(this, getAppBrowserControlsVisibilityDelegate(),
getShareDelegateSupplier(), mEphemeralTabCoordinatorSupplier,
((TabbedRootUiCoordinator) mRootUiCoordinator)::onContextMenuCopyLink,
mRootUiCoordinator.getBottomSheetController());
};
......
......@@ -34,6 +34,7 @@ public class TabbedModeTabDelegateFactory implements TabDelegateFactory {
private final BrowserControlsVisibilityDelegate mAppBrowserControlsVisibilityDelegate;
private final Supplier<ShareDelegate> mShareDelegateSupplier;
private final Supplier<EphemeralTabCoordinator> mEphemeralTabCoordinatorSupplier;
private final Runnable mContextMenuCopyLinkObserver;
private final BottomSheetController mBottomSheetController;
private NativePageFactory mNativePageFactory;
......@@ -41,11 +42,12 @@ public class TabbedModeTabDelegateFactory implements TabDelegateFactory {
BrowserControlsVisibilityDelegate appBrowserControlsVisibilityDelegate,
Supplier<ShareDelegate> shareDelegateSupplier,
Supplier<EphemeralTabCoordinator> ephemeralTabCoordinatorSupplier,
BottomSheetController sheetController) {
Runnable contextMenuCopyLinkObserver, BottomSheetController sheetController) {
mActivity = activity;
mAppBrowserControlsVisibilityDelegate = appBrowserControlsVisibilityDelegate;
mShareDelegateSupplier = shareDelegateSupplier;
mEphemeralTabCoordinatorSupplier = ephemeralTabCoordinatorSupplier;
mContextMenuCopyLinkObserver = contextMenuCopyLinkObserver;
mBottomSheetController = sheetController;
}
......@@ -63,7 +65,8 @@ public class TabbedModeTabDelegateFactory implements TabDelegateFactory {
public ContextMenuPopulatorFactory createContextMenuPopulatorFactory(Tab tab) {
return new ChromeContextMenuPopulatorFactory(
new TabContextMenuItemDelegate(tab, mActivity.getTabModelSelector(),
mEphemeralTabCoordinatorSupplier, mActivity::getSnackbarManager),
mEphemeralTabCoordinatorSupplier, mContextMenuCopyLinkObserver,
mActivity::getSnackbarManager),
mShareDelegateSupplier, ChromeContextMenuPopulator.ContextMenuMode.NORMAL,
AppHooks.get().getExternalAuthUtils());
}
......
......@@ -62,7 +62,6 @@ import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
import org.chromium.chrome.browser.IntentHandler.TabOpenType;
import org.chromium.chrome.browser.PlayServicesVersionInfo;
import org.chromium.chrome.browser.TabbedModeTabDelegateFactory;
import org.chromium.chrome.browser.WarmupManager;
import org.chromium.chrome.browser.accessibility.FontSizePrefs;
import org.chromium.chrome.browser.app.appmenu.AppMenuPropertiesDelegateImpl;
......@@ -137,7 +136,6 @@ import org.chromium.chrome.browser.sync.ProfileSyncService;
import org.chromium.chrome.browser.sync.SyncController;
import org.chromium.chrome.browser.tab.AccessibilityVisibilityHandler;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabDelegateFactory;
import org.chromium.chrome.browser.tab.TabHidingType;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.tab.TabSelectionType;
......@@ -172,7 +170,6 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
import org.chromium.components.browser_ui.notifications.NotificationManagerProxy;
import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl;
import org.chromium.components.browser_ui.util.ComposedBrowserControlsVisibilityDelegate;
import org.chromium.components.browser_ui.widget.InsetObserverView;
import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
import org.chromium.components.browser_ui.widget.textbubble.TextBubble;
......@@ -1561,12 +1558,6 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
return mActivityTabProvider;
}
public TabDelegateFactory getTabDelegateFactory() {
return new TabbedModeTabDelegateFactory(this,
new ComposedBrowserControlsVisibilityDelegate(), getShareDelegateSupplier(), null,
mRootUiCoordinator.getBottomSheetController());
}
/**
* Returns the {@link InsetObserverView} that has the current system window
* insets information.
......
......@@ -23,12 +23,15 @@ import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
import org.chromium.chrome.browser.bookmarks.BookmarkListEntry.ViewType;
import org.chromium.chrome.browser.bookmarks.BookmarkRow.Location;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.signin.PersonalizedSigninPromoView;
import org.chromium.chrome.browser.sync.ProfileSyncService;
import org.chromium.components.bookmarks.BookmarkId;
import org.chromium.components.bookmarks.BookmarkType;
import org.chromium.components.browser_ui.widget.dragreorder.DragReorderableListAdapter;
import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter;
import org.chromium.components.feature_engagement.EventConstants;
import java.util.ArrayList;
import java.util.List;
......@@ -310,6 +313,11 @@ class BookmarkItemsAdapter extends DragReorderableListAdapter<BookmarkListEntry>
} else {
setBookmarks(mDelegate.getModel().getChildIDs(folder));
}
if (folder.getType() == BookmarkType.READING_LIST) {
TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile())
.notifyEvent(EventConstants.READ_LATER_BOOKMARK_FOLDER_OPENED);
}
}
@Override
......
......@@ -24,8 +24,10 @@ import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
......@@ -34,6 +36,7 @@ import org.chromium.components.bookmarks.BookmarkId;
import org.chromium.components.bookmarks.BookmarkType;
import org.chromium.components.browser_ui.widget.TintedDrawable;
import org.chromium.components.embedder_support.util.UrlConstants;
import org.chromium.components.feature_engagement.EventConstants;
import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.base.PageTransition;
......@@ -135,6 +138,9 @@ public class BookmarkUtils {
new SnackbarController() {}, Snackbar.TYPE_ACTION,
Snackbar.UMA_READING_LIST_BOOKMARK_ADDED);
snackbarManager.showSnackbar(snackbar);
TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile())
.notifyEvent(EventConstants.READ_LATER_ARTICLE_SAVED);
}
});
}
......
......@@ -477,7 +477,7 @@ public class CustomTabDelegateFactory implements TabDelegateFactory {
new TabContextMenuItemDelegate(tab, tabModelSelector,
EphemeralTabCoordinator.isSupported() ? mEphemeralTabCoordinator::get : ()
-> null,
mActivity == null ? null : mActivity::getSnackbarManager),
() -> {}, mActivity == null ? null : mActivity::getSnackbarManager),
shareDelegateSupplier, contextMenuMode, AppHooks.get().getExternalAuthUtils());
}
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.read_later;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
import org.chromium.chrome.browser.user_education.IPHCommandBuilder;
import org.chromium.chrome.browser.user_education.UserEducationHelper;
import org.chromium.components.feature_engagement.FeatureConstants;
/**
* Controller to manage when and how we show read later in-product-help messages to users.
*/
public class ReadLaterIPHController {
private final UserEducationHelper mUserEducationHelper;
private final AppMenuHandler mAppMenuHandler;
private final View mToolbarMenuButton;
/**
* Constructor.
* @param activity The current activity.
* @param toolbarMenuButton The toolbar menu button to which IPH will be anchored.
* @param appMenuHandler The app menu handler
*/
public ReadLaterIPHController(
Activity activity, View toolbarMenuButton, AppMenuHandler appMenuHandler) {
mToolbarMenuButton = toolbarMenuButton;
mAppMenuHandler = appMenuHandler;
mUserEducationHelper = new UserEducationHelper(activity,
new Handler(Looper.getMainLooper()), TrackerFactory::getTrackerForProfile);
}
/**
* Attempts to show an IPH text bubble about the read later option in app menu.
*/
public void onCopyContextMenuItemClicked() {
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.READ_LATER)) return;
mUserEducationHelper.requestShowIPH(
new IPHCommandBuilder(mToolbarMenuButton.getContext().getResources(),
FeatureConstants.READ_LATER_APP_MENU_BOOKMARK_THIS_PAGE_FEATURE,
R.string.reading_list_save_pages_for_later,
R.string.reading_list_save_pages_for_later)
.setAnchorView(mToolbarMenuButton)
.setOnShowCallback(
() -> turnOnHighlightForMenuItem(R.id.bookmark_this_page_id))
.setOnDismissCallback(this::turnOffHighlightForMenuItem)
.build());
}
/**
* Attempts to show an IPH text bubble after a cold start.
*/
public void showColdStartIPH() {
showReadLaterAppMenuBookmarksIPH();
}
private void showReadLaterAppMenuBookmarksIPH() {
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.READ_LATER)) return;
mUserEducationHelper.requestShowIPH(
new IPHCommandBuilder(mToolbarMenuButton.getContext().getResources(),
FeatureConstants.READ_LATER_APP_MENU_BOOKMARKS_FEATURE,
R.string.reading_list_find_in_bookmarks,
R.string.reading_list_find_in_bookmarks)
.setAnchorView(mToolbarMenuButton)
.setOnShowCallback(
() -> turnOnHighlightForMenuItem(R.id.all_bookmarks_menu_id))
.setOnDismissCallback(this::turnOffHighlightForMenuItem)
.build());
}
private void turnOnHighlightForMenuItem(int highlightMenuItemId) {
mAppMenuHandler.setMenuHighlight(highlightMenuItemId);
}
private void turnOffHighlightForMenuItem() {
mAppMenuHandler.clearMenuHighlight();
}
}
......@@ -7,6 +7,7 @@ include_rules = [
"+chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java",
"+chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java",
"+chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java",
"+chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/TrackerFactory.java",
"+chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java",
"+chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureNotificationServiceImpl.java",
"+chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewTabHelper.java",
......
......@@ -25,15 +25,18 @@ import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTa
import org.chromium.chrome.browser.contextmenu.ContextMenuItemDelegate;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.download.ChromeDownloadDelegate;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.incognito.IncognitoUtils;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
import org.chromium.components.embedder_support.util.UrlConstants;
import org.chromium.components.embedder_support.util.UrlUtilities;
import org.chromium.components.feature_engagement.EventConstants;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.common.Referrer;
......@@ -52,6 +55,7 @@ public class TabContextMenuItemDelegate implements ContextMenuItemDelegate {
private boolean mLoadOriginalImageRequestedForPageLoad;
private EmptyTabObserver mDataReductionProxyContextMenuTabObserver;
private final Supplier<EphemeralTabCoordinator> mEphemeralTabCoordinatorSupplier;
private final Runnable mContextMenuCopyLinkObserver;
private final Supplier<SnackbarManager> mSnackbarManagerSupplier;
/**
......@@ -59,10 +63,12 @@ public class TabContextMenuItemDelegate implements ContextMenuItemDelegate {
*/
public TabContextMenuItemDelegate(Tab tab, TabModelSelector tabModelSelector,
Supplier<EphemeralTabCoordinator> ephemeralTabCoordinatorSupplier,
Runnable contextMenuCopyLinkObserver,
Supplier<SnackbarManager> snackbarManagerSupplier) {
mTab = (TabImpl) tab;
mTabModelSelector = tabModelSelector;
mEphemeralTabCoordinatorSupplier = ephemeralTabCoordinatorSupplier;
mContextMenuCopyLinkObserver = contextMenuCopyLinkObserver;
mSnackbarManagerSupplier = snackbarManagerSupplier;
mDataReductionProxyContextMenuTabObserver = new EmptyTabObserver() {
......@@ -119,6 +125,10 @@ public class TabContextMenuItemDelegate implements ContextMenuItemDelegate {
@Override
public void onSaveToClipboard(String text, int clipboardType) {
Clipboard.getInstance().setText(text);
if (clipboardType == ClipboardType.LINK_URL) {
// TODO(crbug/1150090): Find a better way of passing event for IPH.
mContextMenuCopyLinkObserver.run();
}
}
@Override
......@@ -262,6 +272,8 @@ public class TabContextMenuItemDelegate implements ContextMenuItemDelegate {
public void onReadLater(String url, String title) {
BookmarkUtils.addToReadingList(
url, title, mSnackbarManagerSupplier.get(), mTab.getContext());
TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile())
.notifyEvent(EventConstants.READ_LATER_CONTEXT_MENU_TAPPED);
}
@Override
......
......@@ -49,6 +49,7 @@ import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.read_later.ReadLaterIPHController;
import org.chromium.chrome.browser.share.ShareDelegate;
import org.chromium.chrome.browser.signin.SigninPromoUtil;
import org.chromium.chrome.browser.status_indicator.StatusIndicatorCoordinator;
......@@ -81,6 +82,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator {
private StatusIndicatorCoordinator.StatusIndicatorObserver mStatusIndicatorObserver;
private OfflineIndicatorControllerV2 mOfflineIndicatorController;
private OfflineIndicatorInProductHelpController mOfflineIndicatorInProductHelpController;
private ReadLaterIPHController mReadLaterIPHController;
private UrlFocusChangeListener mUrlFocusChangeListener;
private @Nullable ToolbarButtonInProductHelpController mToolbarButtonInProductHelpController;
private AppBannerInProductHelpController mAppBannerInProductHelpController;
......@@ -326,10 +328,13 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator {
}
};
mToolbarButtonIphTabSupplier.set(activityTabProvider.get());
mReadLaterIPHController = new ReadLaterIPHController(mActivity,
getToolbarManager().getMenuButtonView(), mAppMenuCoordinator.getAppMenuHandler());
boolean didTriggerPromo = triggerPromo(intentWithEffect);
if (!didTriggerPromo) {
mToolbarButtonInProductHelpController.showColdStartIPH();
mReadLaterIPHController.showColdStartIPH();
}
if (ChromeFeatureList.isEnabled(ChromeFeatureList.TOOLBAR_IPH_ANDROID)) {
mPromoShownOneshotSupplier.set(didTriggerPromo);
......@@ -459,6 +464,12 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator {
return mNavigationSheet;
}
/** Called when a link is copied through context menu. */
public void onContextMenuCopyLink() {
// TODO(crbug/1150090): Find a better way of passing event for IPH.
mReadLaterIPHController.onCopyContextMenuItemClicked();
}
/**
* Triggers the display of an appropriate promo, if any, returning true if a promo is actually
* displayed.
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.read_later;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.chromium.chrome.browser.toolbar.top.ButtonHighlightMatcher.withHighlight;
import static org.chromium.chrome.test.util.ViewUtils.waitForView;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import android.view.View;
import androidx.test.espresso.ViewInteraction;
import androidx.test.espresso.matcher.RootMatchers;
import androidx.test.filters.MediumTest;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.chromium.base.Callback;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.contextmenu.RevampedContextMenuUtils;
import org.chromium.components.feature_engagement.EventConstants;
import org.chromium.components.feature_engagement.FeatureConstants;
import org.chromium.components.feature_engagement.Tracker;
import org.chromium.net.test.EmbeddedTestServerRule;
import org.chromium.ui.test.util.UiRestriction;
/** Integration tests for showing IPH bubbles for read later. */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Features.EnableFeatures(ChromeFeatureList.READ_LATER)
@Batch(Batch.PER_CLASS)
public class ReadLaterIphTest {
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Rule
public EmbeddedTestServerRule mTestServer = new EmbeddedTestServerRule();
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock
private Tracker mTracker;
private static final String CONTEXT_MENU_TEST_URL =
"/chrome/test/data/android/contextmenu/context_menu_test.html";
private static final String CONTEXT_MENU_LINK_DOM_ID = "testLink";
@Before
public void setUp() {
Looper.prepare();
// Pretend the feature engagement feature is already initialized. Otherwise
// UserEducationHelper#requestShowIPH() calls get dropped during test.
doAnswer(invocation -> {
invocation.<Callback<Boolean>>getArgument(0).onResult(true);
return null;
})
.when(mTracker)
.addOnInitializedCallback(any());
TrackerFactory.setTrackerForTests(mTracker);
mActivityTestRule.startMainActivityOnBlankPage();
}
@After
public void tearDown() throws Exception {
TrackerFactory.setTrackerForTests(null);
}
@Test
@MediumTest
@Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
public void testShowIPHOnContextMenuLinkCopied() throws Throwable {
when(mTracker.shouldTriggerHelpUI(
FeatureConstants.READ_LATER_APP_MENU_BOOKMARK_THIS_PAGE_FEATURE))
.thenReturn(true);
mActivityTestRule.loadUrlInNewTab(mTestServer.getServer().getURL(CONTEXT_MENU_TEST_URL));
ChromeActivity activity = mActivityTestRule.getActivity();
Tab tab = activity.getActivityTab();
RevampedContextMenuUtils.selectContextMenuItem(InstrumentationRegistry.getInstrumentation(),
activity, tab, CONTEXT_MENU_LINK_DOM_ID, R.id.contextmenu_copy_link_address);
onView(withId(R.id.menu_button_wrapper)).check(matches(withHighlight(true)));
waitForHelpBubble(withText(R.string.reading_list_save_pages_for_later));
}
@Test
@MediumTest
@Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
public void testShowBookmarksReadLaterIPH() throws Throwable {
mActivityTestRule.loadUrl(mTestServer.getServer().getURL(CONTEXT_MENU_TEST_URL));
ChromeActivity activity = mActivityTestRule.getActivity();
Tab tab = activity.getActivityTab();
RevampedContextMenuUtils.selectContextMenuItem(InstrumentationRegistry.getInstrumentation(),
activity, tab, CONTEXT_MENU_LINK_DOM_ID, R.id.contextmenu_read_later);
verify(mTracker, times(1)).notifyEvent(EventConstants.READ_LATER_CONTEXT_MENU_TAPPED);
}
private ViewInteraction waitForHelpBubble(Matcher<View> matcher) {
View mainDecorView = mActivityTestRule.getActivity().getWindow().getDecorView();
return onView(isRoot())
.inRoot(RootMatchers.withDecorView(not(is(mainDecorView))))
.check(waitForView(matcher));
}
}
......@@ -72,11 +72,13 @@ public class TabUmaTest {
private TabbedModeTabDelegateFactory createTabDelegateFactory() {
BrowserControlsVisibilityDelegate visibilityDelegate =
new BrowserControlsVisibilityDelegate(BrowserControlsState.BOTH) {};
// clang-format off
return new TabbedModeTabDelegateFactory(mActivityTestRule.getActivity(), visibilityDelegate,
new ObservableSupplierImpl<ShareDelegate>(), null,
mActivityTestRule.getActivity()
() -> {}, mActivityTestRule.getActivity()
.getRootUiCoordinatorForTesting()
.getBottomSheetController());
// clang-format on
}
private Tab createLazilyLoadedTab(boolean show) throws ExecutionException {
......
dtrainor@chromium.org
shaktisahu@chromium.org
xingliu@chromium.org
# Backup reviewers:
......
......@@ -180,6 +180,12 @@ public final class EventConstants {
public static final String TAB_SWITCHER_BUTTON_CLICKED = "tab_switcher_button_clicked";
/** Read later related events. */
public static final String READ_LATER_CONTEXT_MENU_TAPPED = "read_later_context_menu_tapped";
public static final String READ_LATER_ARTICLE_SAVED = "read_later_article_saved";
public static final String READ_LATER_BOOKMARK_FOLDER_OPENED =
"read_later_bookmark_folder_opened";
/** Video tutorial related events. */
public static final String VIDEO_TUTORIAL_DISMISSED_SUMMARY =
"video_tutorial_iph_dismissed_summary";
......
......@@ -65,6 +65,8 @@ public @interface FeatureConstants {
String TRANSLATE_MENU_BUTTON_FEATURE = "IPH_TranslateMenuButton";
String EXPLORE_SITES_TILE_FEATURE = "IPH_ExploreSitesTile";
String READ_LATER_CONTEXT_MENU_FEATURE = "IPH_ReadLaterContextMenu";
String READ_LATER_APP_MENU_BOOKMARK_THIS_PAGE_FEATURE = "IPH_ReadLaterAppMenuBookmarkThisPage";
String READ_LATER_APP_MENU_BOOKMARKS_FEATURE = "IPH_ReadLaterAppMenuBookmarks";
/**
* An IPH feature that encourages users to get better translations by enabling access to page
......
......@@ -77,6 +77,10 @@ const base::Feature kIPHQuietNotificationPromptsFeature{
"IPH_QuietNotificationPrompts", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHReadLaterContextMenuFeature{
"IPH_ReadLaterContextMenu", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHReadLaterAppMenuBookmarkThisPageFeature{
"IPH_ReadLaterAppMenuBookmarkThisPage", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHReadLaterAppMenuBookmarksFeature{
"IPH_ReadLaterAppMenuBookmarks", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHEphemeralTabFeature{"IPH_EphemeralTab",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHFeedCardMenuFeature{"IPH_FeedCardMenu",
......
......@@ -66,6 +66,8 @@ extern const base::Feature kIPHNewTabPageHomeButtonFeature;
extern const base::Feature kIPHPreviewsOmniboxUIFeature;
extern const base::Feature kIPHQuietNotificationPromptsFeature;
extern const base::Feature kIPHReadLaterContextMenuFeature;
extern const base::Feature kIPHReadLaterAppMenuBookmarkThisPageFeature;
extern const base::Feature kIPHReadLaterAppMenuBookmarksFeature;
extern const base::Feature kIPHTabGroupsQuicklyComparePagesFeature;
extern const base::Feature kIPHTabGroupsTapToSeeAnotherTabFeature;
extern const base::Feature kIPHTabGroupsYourTabsAreTogetherFeature;
......
......@@ -50,6 +50,8 @@ const base::Feature* const kAllFeatures[] = {
&kIPHPwaInstallAvailableFeature,
&kIPHQuietNotificationPromptsFeature,
&kIPHReadLaterContextMenuFeature,
&kIPHReadLaterAppMenuBookmarkThisPageFeature,
&kIPHReadLaterAppMenuBookmarksFeature,
&kIPHTabGroupsQuicklyComparePagesFeature,
&kIPHTabGroupsTapToSeeAnotherTabFeature,
&kIPHTabGroupsYourTabsAreTogetherFeature,
......
......@@ -101,6 +101,10 @@ DEFINE_VARIATION_PARAM(kIPHQuietNotificationPromptsFeature,
"IPH_QuietNotificationPrompts");
DEFINE_VARIATION_PARAM(kIPHReadLaterContextMenuFeature,
"IPH_ReadLaterContextMenu");
DEFINE_VARIATION_PARAM(kIPHReadLaterAppMenuBookmarkThisPageFeature,
"IPH_ReadLaterAppMenuBookmarkThisPage");
DEFINE_VARIATION_PARAM(kIPHReadLaterAppMenuBookmarksFeature,
"IPH_ReadLaterAppMenuBookmarks");
DEFINE_VARIATION_PARAM(kIPHTabGroupsQuicklyComparePagesFeature,
"IPH_TabGroupsQuicklyComparePages");
DEFINE_VARIATION_PARAM(kIPHTabGroupsTapToSeeAnotherTabFeature,
......@@ -195,6 +199,8 @@ constexpr flags_ui::FeatureEntry::FeatureVariation
VARIATION_ENTRY(kIPHPwaInstallAvailableFeature),
VARIATION_ENTRY(kIPHQuietNotificationPromptsFeature),
VARIATION_ENTRY(kIPHReadLaterContextMenuFeature),
VARIATION_ENTRY(kIPHReadLaterAppMenuBookmarkThisPageFeature),
VARIATION_ENTRY(kIPHReadLaterAppMenuBookmarksFeature),
VARIATION_ENTRY(kIPHTabGroupsQuicklyComparePagesFeature),
VARIATION_ENTRY(kIPHTabGroupsTapToSeeAnotherTabFeature),
VARIATION_ENTRY(kIPHTabGroupsYourTabsAreTogetherFeature),
......
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