Commit f969d001 authored by Gang Wu's avatar Gang Wu Committed by Commit Bot

Added a metric to record users selected similar items in app menu

This metric is added to record that users come back to app menu and
select a similar menu item in short period (10 seconds) of time.

Bug: 1143780
Change-Id: I5f5522e4b77103d324b6ebe02a2f832d43d81a3a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2508351
Commit-Queue: Gang Wu <gangwu@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823239}
parent 9ccd1018
......@@ -11,6 +11,7 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Pair;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
......@@ -65,7 +66,12 @@ import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.modaldialog.ModalDialogManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Base implementation of {@link AppMenuPropertiesDelegate} that handles hiding and showing menu
......@@ -100,6 +106,13 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
private int mAddAppTitleShown;
private final ModalDialogManager mModalDialogManager;
// The keys of the Map are menuitem ids, the first elements in the Pair are menuitem ids,
// and the second elements in the Pair are AppMenuSimilarSelectionType. If users first
// selected the menuitems in the Pair.first, and then selected a menuitem which is the key
// if the Map, then users' selection match the pattern Pair.second.
private static final Map<Integer, Pair<Set<Integer>, Integer>> sSimilarSelectedMenuItemMap =
createSimilarSelectedMap();
@VisibleForTesting
@IntDef({MenuGroup.INVALID, MenuGroup.PAGE_MENU, MenuGroup.OVERVIEW_MODE_MENU,
MenuGroup.START_SURFACE_MODE_MENU, MenuGroup.TABLET_EMPTY_MODE_MENU})
......@@ -127,6 +140,23 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
int ADD_TO_OPTION = 3;
}
/**
* Keep this list sync with AppMenuSimilarSelectionType in enums.xml.
*/
@IntDef({AppMenuSimilarSelectionType.NO_MATCH,
AppMenuSimilarSelectionType.BOOKMARK_PAGE_THEN_ALL_BOOKMARKS,
AppMenuSimilarSelectionType.ALL_BOOKMARKS_THEN_BOOKMARK_PAGE,
AppMenuSimilarSelectionType.DOWNLOAD_PAGE_THEN_ALL_DOWNLOADS,
AppMenuSimilarSelectionType.ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE})
@interface AppMenuSimilarSelectionType {
int NO_MATCH = -1;
int BOOKMARK_PAGE_THEN_ALL_BOOKMARKS = 0;
int ALL_BOOKMARKS_THEN_BOOKMARK_PAGE = 1;
int DOWNLOAD_PAGE_THEN_ALL_DOWNLOADS = 2;
int ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE = 3;
int NUM_ENTRIES = 4;
}
protected @Nullable OverviewModeBehavior mOverviewModeBehavior;
protected BookmarkBridge mBookmarkBridge;
protected Runnable mAppMenuInvalidator;
......@@ -969,4 +999,70 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
}
return R.id.offline_page_id;
}
@Override
public boolean recordAppMenuSimilarSelectionIfNeeded(
int previousMenuItemId, int currentMenuItemId) {
@AppMenuSimilarSelectionType
int pattern = findSimilarSelectionPattern(previousMenuItemId, currentMenuItemId);
if (pattern == AppMenuSimilarSelectionType.NO_MATCH) {
return false;
}
RecordHistogram.recordEnumeratedHistogram("Mobile.AppMenu.SimilarSelection", pattern,
AppMenuSimilarSelectionType.NUM_ENTRIES);
return true;
}
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public @AppMenuSimilarSelectionType int findSimilarSelectionPattern(
int previousMenuItemId, int currentMenuItemId) {
Pair<Set<Integer>, Integer> menuItemToSelectType =
sSimilarSelectedMenuItemMap.get(currentMenuItemId);
if (menuItemToSelectType != null
&& menuItemToSelectType.first.contains(previousMenuItemId)) {
return menuItemToSelectType.second;
}
return AppMenuSimilarSelectionType.NO_MATCH;
}
private static Map<Integer, Pair<Set<Integer>, Integer>> createSimilarSelectedMap() {
Map<Integer, Pair<Set<Integer>, Integer>> map = new LinkedHashMap<>();
map.put(R.id.all_bookmarks_menu_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.bookmark_this_page_id,
R.id.bookmark_this_page_chip_id, R.id.add_to_bookmarks_menu_id)),
AppMenuSimilarSelectionType.BOOKMARK_PAGE_THEN_ALL_BOOKMARKS));
map.put(R.id.bookmark_this_page_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.all_bookmarks_menu_id)),
AppMenuSimilarSelectionType.ALL_BOOKMARKS_THEN_BOOKMARK_PAGE));
map.put(R.id.bookmark_this_page_chip_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.all_bookmarks_menu_id)),
AppMenuSimilarSelectionType.ALL_BOOKMARKS_THEN_BOOKMARK_PAGE));
map.put(R.id.add_to_bookmarks_menu_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.all_bookmarks_menu_id)),
AppMenuSimilarSelectionType.ALL_BOOKMARKS_THEN_BOOKMARK_PAGE));
map.put(R.id.downloads_menu_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.offline_page_id, R.id.offline_page_chip_id,
R.id.add_to_downloads_menu_id)),
AppMenuSimilarSelectionType.DOWNLOAD_PAGE_THEN_ALL_DOWNLOADS));
map.put(R.id.offline_page_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.downloads_menu_id)),
AppMenuSimilarSelectionType.ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE));
map.put(R.id.offline_page_chip_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.downloads_menu_id)),
AppMenuSimilarSelectionType.ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE));
map.put(R.id.add_to_downloads_menu_id,
new Pair<Set<Integer>, Integer>(
new HashSet<>(Arrays.asList(R.id.downloads_menu_id)),
AppMenuSimilarSelectionType.ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE));
return map;
}
}
......@@ -37,6 +37,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.app.appmenu.AppMenuPropertiesDelegateImpl.AppMenuSimilarSelectionType;
import org.chromium.chrome.browser.app.appmenu.AppMenuPropertiesDelegateImpl.MenuGroup;
import org.chromium.chrome.browser.banners.AppBannerManager;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
......@@ -694,6 +695,110 @@ public class AppMenuPropertiesDelegateUnitTest {
menu.findItem(R.id.get_image_descriptions_id).getTitle());
}
@Test
public void testMenuItems_AppMenuSimilarSelectionChecker() {
Assert.assertEquals("No match for bookmark page then all bookmarks",
AppMenuSimilarSelectionType.BOOKMARK_PAGE_THEN_ALL_BOOKMARKS,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.bookmark_this_page_id, R.id.all_bookmarks_menu_id));
Assert.assertEquals("No match for bookmark page then all bookmarks",
AppMenuSimilarSelectionType.BOOKMARK_PAGE_THEN_ALL_BOOKMARKS,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.bookmark_this_page_chip_id, R.id.all_bookmarks_menu_id));
Assert.assertEquals("No match for bookmark page then all bookmarks",
AppMenuSimilarSelectionType.BOOKMARK_PAGE_THEN_ALL_BOOKMARKS,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.add_to_bookmarks_menu_id, R.id.all_bookmarks_menu_id));
Assert.assertTrue("Should return true for bookmark page then all bookmarks",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.bookmark_this_page_id, R.id.all_bookmarks_menu_id));
Assert.assertTrue("Should return true for bookmark page then all bookmarks",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.bookmark_this_page_chip_id, R.id.all_bookmarks_menu_id));
Assert.assertTrue("Should return true for bookmark page then all bookmarks",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.add_to_bookmarks_menu_id, R.id.all_bookmarks_menu_id));
Assert.assertEquals("No match for all bookmarks then bookmark page",
AppMenuSimilarSelectionType.ALL_BOOKMARKS_THEN_BOOKMARK_PAGE,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.all_bookmarks_menu_id, R.id.bookmark_this_page_id));
Assert.assertEquals("No match for all bookmarks then bookmark page",
AppMenuSimilarSelectionType.ALL_BOOKMARKS_THEN_BOOKMARK_PAGE,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.all_bookmarks_menu_id, R.id.bookmark_this_page_chip_id));
Assert.assertEquals("No match for all bookmarks then bookmark page",
AppMenuSimilarSelectionType.ALL_BOOKMARKS_THEN_BOOKMARK_PAGE,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.all_bookmarks_menu_id, R.id.add_to_bookmarks_menu_id));
Assert.assertTrue("Should return true for all bookmarks then bookmark page",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.all_bookmarks_menu_id, R.id.bookmark_this_page_id));
Assert.assertTrue("Should return true for all bookmarks then bookmark page",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.all_bookmarks_menu_id, R.id.bookmark_this_page_chip_id));
Assert.assertTrue("Should return true for all bookmarks then bookmark page",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.all_bookmarks_menu_id, R.id.add_to_bookmarks_menu_id));
Assert.assertEquals("No match for download page then all downloads",
AppMenuSimilarSelectionType.DOWNLOAD_PAGE_THEN_ALL_DOWNLOADS,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.offline_page_id, R.id.downloads_menu_id));
Assert.assertEquals("No match for download page then all downloads",
AppMenuSimilarSelectionType.DOWNLOAD_PAGE_THEN_ALL_DOWNLOADS,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.offline_page_chip_id, R.id.downloads_menu_id));
Assert.assertEquals("No match for download page then all downloads",
AppMenuSimilarSelectionType.DOWNLOAD_PAGE_THEN_ALL_DOWNLOADS,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.add_to_downloads_menu_id, R.id.downloads_menu_id));
Assert.assertTrue("Should return true for download page then all downloads",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.offline_page_id, R.id.downloads_menu_id));
Assert.assertTrue("Should return true for download page then all downloads",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.offline_page_chip_id, R.id.downloads_menu_id));
Assert.assertTrue("Should return true for download page then all downloads",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.add_to_downloads_menu_id, R.id.downloads_menu_id));
Assert.assertEquals("No match for all downloads then download page",
AppMenuSimilarSelectionType.ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.downloads_menu_id, R.id.offline_page_id));
Assert.assertEquals("No match for all downloads then download page",
AppMenuSimilarSelectionType.ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.downloads_menu_id, R.id.offline_page_chip_id));
Assert.assertEquals("No match for all downloads then download page",
AppMenuSimilarSelectionType.ALL_DOWNLOADS_THEN_DOWNLOAD_PAGE,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.downloads_menu_id, R.id.add_to_downloads_menu_id));
Assert.assertTrue("Should return true for all downloads then download page",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.downloads_menu_id, R.id.offline_page_id));
Assert.assertTrue("Should return true for all downloads then download page",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.downloads_menu_id, R.id.offline_page_chip_id));
Assert.assertTrue("Should return true for all downloads then download page",
mAppMenuPropertiesDelegate.recordAppMenuSimilarSelectionIfNeeded(
R.id.downloads_menu_id, R.id.add_to_downloads_menu_id));
Assert.assertEquals("Should no match for all downloads then all bookmarks",
AppMenuSimilarSelectionType.NO_MATCH,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.downloads_menu_id, R.id.all_bookmarks_menu_id));
Assert.assertEquals("Should no match for all bookmarks then share",
AppMenuSimilarSelectionType.NO_MATCH,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.all_bookmarks_menu_id, R.id.share_menu_button_id));
Assert.assertEquals("Should no match for new tab then find in page",
AppMenuSimilarSelectionType.NO_MATCH,
mAppMenuPropertiesDelegate.findSimilarSelectionPattern(
R.id.new_tab_menu_id, R.id.find_in_page_id));
}
private void setUpMocksForPageMenu() {
when(mActivityTabProvider.get()).thenReturn(mTab);
when(mOverviewModeBehavior.overviewVisible()).thenReturn(false);
......
......@@ -13,6 +13,8 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.SystemClock;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Pair;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
......@@ -43,8 +45,10 @@ import org.chromium.chrome.browser.ui.appmenu.internal.R;
import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter;
import org.chromium.ui.widget.Toast;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
/**
* Shows a popup of menuitems anchored to a host view. When a item is selected we call
......@@ -54,6 +58,8 @@ import java.util.List;
*/
class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler {
private static final float LAST_ITEM_SHOW_FRACTION = 0.5f;
@VisibleForTesting
static final long RECENT_SELECTED_MENUITEM_EXPIRATION_MS = 10 * DateUtils.SECOND_IN_MILLIS;
private final Menu mMenu;
private final int mItemRowHeight;
......@@ -66,7 +72,8 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
private PopupWindow mPopup;
private ListView mListView;
private AppMenuAdapter mAdapter;
private AppMenuHandlerImpl mHandler;
@VisibleForTesting
AppMenuHandlerImpl mHandler;
private View mFooterView;
private int mCurrentScreenRotation = -1;
private boolean mIsByPermanentButton;
......@@ -74,6 +81,9 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
private long mMenuShownTimeMs;
private boolean mSelectedItemBeforeDismiss;
// Selected menu item id and the timestamp.
private final Queue<Pair<Integer, Long>> mRecentSelectedMenuItems = new ArrayDeque<>();
/**
* Creates and sets up the App Menu.
* @param menu Original menu created by the framework.
......@@ -349,6 +359,7 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
@Override
public void onItemClick(MenuItem menuItem) {
if (menuItem.isEnabled()) {
recordSelectedMenuItem(menuItem.getItemId(), SystemClock.elapsedRealtime());
mSelectedItemBeforeDismiss = true;
dismiss();
mHandler.onOptionsItemSelected(menuItem);
......@@ -590,4 +601,27 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuClickHandler
}
return mItemRowHeight;
}
@VisibleForTesting
void recordSelectedMenuItem(int menuItemId, long timestamp) {
// Remove the selected MenuItems older than RECENT_SELECTED_MENUITEM_EXPIRATION_MS.
while (!mRecentSelectedMenuItems.isEmpty()
&& (timestamp - mRecentSelectedMenuItems.peek().second
> RECENT_SELECTED_MENUITEM_EXPIRATION_MS)) {
mRecentSelectedMenuItems.remove();
}
recordSelectionSequence(menuItemId);
mRecentSelectedMenuItems.add(new Pair<Integer, Long>(menuItemId, timestamp));
}
private void recordSelectionSequence(int menuItemId) {
for (Pair<Integer, Long> previousSelectedMenuItem : mRecentSelectedMenuItems) {
if (mHandler.recordAppMenuSimilarSelectionIfNeeded(
previousSelectedMenuItem.first, menuItemId)) {
// Only record the similar selection once for one user action.
return;
}
}
}
}
......@@ -358,4 +358,16 @@ class AppMenuHandlerImpl
AppMenuPropertiesDelegate getDelegateForTests() {
return mDelegate;
}
/**
* Record the user selections if users make selected similar MenuItems.
*
* @param previousMenuItemId The previous selected MenuItem Id.
* @param currentMenuItemId The current selected MenuItem Id.
* @return Whether the selections is recorded.
*/
boolean recordAppMenuSimilarSelectionIfNeeded(int previousMenuItemId, int currentMenuItemId) {
return mDelegate.recordAppMenuSimilarSelectionIfNeeded(
previousMenuItemId, currentMenuItemId);
}
}
......@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.ui.appmenu;
import static org.mockito.ArgumentMatchers.anyInt;
import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.Menu;
......@@ -760,6 +762,30 @@ public class AppMenuTest extends DummyUiActivityTestCase {
Assert.assertEquals(15, height);
}
@Test
@SmallTest
public void testRecordSelectedMenuItem() throws TimeoutException {
showMenuAndAssert();
AppMenu appMenu = mAppMenuHandler.getAppMenu();
AppMenuHandlerImpl spiedHandler = Mockito.spy(mAppMenuHandler);
appMenu.mHandler = spiedHandler;
appMenu.recordSelectedMenuItem(R.id.menu_item_one, 1);
Mockito.verify(spiedHandler, Mockito.times(0))
.recordAppMenuSimilarSelectionIfNeeded(anyInt(), anyInt());
appMenu.recordSelectedMenuItem(R.id.menu_item_two, 2);
Mockito.verify(spiedHandler, Mockito.times(1))
.recordAppMenuSimilarSelectionIfNeeded(R.id.menu_item_one, R.id.menu_item_two);
appMenu.recordSelectedMenuItem(
R.id.menu_item_three, AppMenu.RECENT_SELECTED_MENUITEM_EXPIRATION_MS + 3);
Mockito.verify(spiedHandler, Mockito.times(0))
.recordAppMenuSimilarSelectionIfNeeded(R.id.menu_item_one, R.id.menu_item_three);
Mockito.verify(spiedHandler, Mockito.times(0))
.recordAppMenuSimilarSelectionIfNeeded(R.id.menu_item_two, R.id.menu_item_three);
}
private void createMenuItem(
List<MenuItem> menuItems, List<Integer> heightList, int id, int height) {
Menu menu = mAppMenuHandler.getAppMenu().getMenu();
......
......@@ -27,6 +27,7 @@ class TestAppMenuPropertiesDelegate implements AppMenuPropertiesDelegate {
public int groupDividerId;
public boolean enableAppIconRow;
public boolean iconBeforeItem;
public boolean recordAppMenuSimilarSelection;
@Override
public void destroy() {}
......@@ -114,4 +115,10 @@ class TestAppMenuPropertiesDelegate implements AppMenuPropertiesDelegate {
public boolean shouldShowIconBeforeItem() {
return iconBeforeItem;
}
@Override
public boolean recordAppMenuSimilarSelectionIfNeeded(
int previousMenuItemId, int currentMenuItemId) {
return recordAppMenuSimilarSelection;
}
}
......@@ -115,4 +115,13 @@ public interface AppMenuPropertiesDelegate {
* should show the icon before the text.
*/
boolean shouldShowIconBeforeItem();
/**
* Record the user selections if users make selected similar MenuItems.
*
* @param previousMenuItemId The previous selected MenuItem Id.
* @param currentMenuItemId The current selected MenuItem Id.
* @return Whether the pattern is recorded.
*/
boolean recordAppMenuSimilarSelectionIfNeeded(int previousMenuItemId, int currentMenuItemId);
}
......@@ -3106,6 +3106,17 @@ Unknown properties are collapsed to zero. -->
<int value="18" label="Printing turned off"/>
</enum>
<enum name="AppMenuSimilarSelectionType">
<int value="0"
label="selected adding to bookmarks, and then selected all bookmarks"/>
<int value="1"
label="selected all bookmarks, and then selected adding to bookmarks"/>
<int value="2"
label="selected downloading the page, and then selected all downloads"/>
<int value="3"
label="selected all downloads, and then selected downloading the page"/>
</enum>
<enum name="AppPromoAction">
<int value="0" label="PROMO_LAUNCH_APP"/>
<int value="1" label="PROMO_LAUNCH_WEB_STORE"/>
......@@ -26,6 +26,19 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
<variant name=".SlowerThanInflation"/>
</variants>
<histogram name="Mobile.AppMenu.SimilarSelection"
enum="AppMenuSimilarSelectionType" expires_after="M95">
<owner>gangwu@chromium.org</owner>
<owner>twellington@chromium.org</owner>
<summary>
Android: This metrics is recorded when users made similar selections on app
menu within a period of time. ex. a user selected downloading the current
page. After 5 seconds, the user opened the app menu again and selected
download manager. In this case, we would consider that Download and Download
Manager are similar selections.
</summary>
</histogram>
<histogram name="Mobile.AppMenu.TimeToTakeAction.Abandoned" units="ms"
expires_after="M93">
<owner>gangwu@chromium.org</owner>
......
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