blob: a871afc375fd29a63a6f1f3c8dbf133fa53998a1 [file] [log] [blame]
// Copyright 2015 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.ntp;
import android.os.SystemClock;
import android.support.annotation.IntDef;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.rappor.RapporServiceBridge;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.util.UrlUtilities;
import org.chromium.ui.base.PageTransition;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.TimeUnit;
/**
* Records UMA stats for which actions the user takes on the NTP in the
* "NewTabPage.ActionAndroid2" histogram.
*/
public final class NewTabPageUma {
private NewTabPageUma() {}
// Possible actions taken by the user on the NTP. These values are also defined in
// histograms.xml. WARNING: these values must stay in sync with histograms.xml.
/** User performed a search using the omnibox. */
private static final int ACTION_SEARCHED_USING_OMNIBOX = 0;
/** User navigated to Google search homepage using the omnibox. */
private static final int ACTION_NAVIGATED_TO_GOOGLE_HOMEPAGE = 1;
/** User navigated to any other page using the omnibox. */
private static final int ACTION_NAVIGATED_USING_OMNIBOX = 2;
/** User opened a most visited tile. */
public static final int ACTION_OPENED_MOST_VISITED_TILE = 3;
/** User opened the recent tabs manager. */
public static final int ACTION_OPENED_RECENT_TABS_MANAGER = 4;
/** User opened the history manager. */
public static final int ACTION_OPENED_HISTORY_MANAGER = 5;
/** User opened the bookmarks manager. */
public static final int ACTION_OPENED_BOOKMARKS_MANAGER = 6;
/** User opened the downloads manager. */
public static final int ACTION_OPENED_DOWNLOADS_MANAGER = 7;
/** User navigated to the webpage for a snippet shown on the NTP. */
public static final int ACTION_OPENED_SNIPPET = 8;
/** User clicked on the "learn more" link in the footer. */
public static final int ACTION_CLICKED_LEARN_MORE = 9;
/** User clicked on the "Refresh" button in the "all dismissed" state. */
public static final int ACTION_CLICKED_ALL_DISMISSED_REFRESH = 10;
/** The number of possible actions. */
private static final int NUM_ACTIONS = 11;
/** User navigated to a page using the omnibox. */
private static final int RAPPOR_ACTION_NAVIGATED_USING_OMNIBOX = 0;
/** User navigated to a page using one of the suggested tiles. */
public static final int RAPPOR_ACTION_VISITED_SUGGESTED_TILE = 1;
/** Regular NTP impression (usually when a new tab is opened). */
public static final int NTP_IMPRESSION_REGULAR = 0;
/** Potential NTP impressions (instead of blank page if no tab is open). */
public static final int NTP_IMPESSION_POTENTIAL_NOTAB = 1;
/** The number of possible NTP impression types */
private static final int NUM_NTP_IMPRESSION = 2;
/** The maximal number of suggestions per section. Keep in sync with kMaxSuggestionsPerCategory
* in content_suggestions_metrics.cc. */
private static final int MAX_SUGGESTIONS_PER_SECTION = 20;
/**
* Possible results when updating content suggestions list in the UI. Keep in sync with the
* ContentSuggestionsUIUpdateResult enum in histograms.xml. Do not remove or change existing
* values other than NUM_UI_UPDATE_RESULTS.
*/
@IntDef({ContentSuggestionsUIUpdateResult.SUCCESS_APPENDED,
ContentSuggestionsUIUpdateResult.SUCCESS_REPLACED,
ContentSuggestionsUIUpdateResult.FAIL_ALL_SEEN,
ContentSuggestionsUIUpdateResult.FAIL_DISABLED})
@Retention(RetentionPolicy.SOURCE)
public @interface ContentSuggestionsUIUpdateResult {
/**
* The content suggestions are successfully appended (because they are set for the first
* time or explicitly marked to be appended).
*/
int SUCCESS_APPENDED = 0;
/**
* Update successful, suggestions were replaced (some of them possibly seen, the exact
* number reported in a separate histogram).
*/
int SUCCESS_REPLACED = 1;
/** Update failed, all previous content suggestions have been seen (and kept). */
int FAIL_ALL_SEEN = 2;
/** Update failed, because it is disabled by a variation parameter. */
int FAIL_DISABLED = 3;
int NUM_ENTRIES = 4;
}
/** The NTP was loaded in a cold startup. */
private static final int LOAD_TYPE_COLD_START = 0;
/** The NTP was loaded in a warm startup. */
private static final int LOAD_TYPE_WARM_START = 1;
/**
* The NTP was loaded at some other time after activity creation and the user interacted with
* the activity in the meantime.
*/
private static final int LOAD_TYPE_OTHER = 2;
/** The number of load types. */
private static final int LOAD_TYPE_COUNT = 3;
/**
* Records an action taken by the user on the NTP.
* @param action One of the ACTION_* values defined in this class.
*/
public static void recordAction(int action) {
assert action >= 0;
assert action < NUM_ACTIONS;
RecordHistogram.recordEnumeratedHistogram("NewTabPage.ActionAndroid2", action, NUM_ACTIONS);
}
/**
* Record that the user has navigated away from the NTP using the omnibox.
* @param destinationUrl The URL to which the user navigated.
* @param transitionType The transition type of the navigation, from PageTransition.java.
*/
public static void recordOmniboxNavigation(String destinationUrl, int transitionType) {
if ((transitionType & PageTransition.CORE_MASK) == PageTransition.GENERATED) {
recordAction(ACTION_SEARCHED_USING_OMNIBOX);
} else {
if (UrlUtilities.nativeIsGoogleHomePageUrl(destinationUrl)) {
recordAction(ACTION_NAVIGATED_TO_GOOGLE_HOMEPAGE);
} else {
recordAction(ACTION_NAVIGATED_USING_OMNIBOX);
}
recordExplicitUserNavigation(destinationUrl, RAPPOR_ACTION_NAVIGATED_USING_OMNIBOX);
}
}
/**
* Record the eTLD+1 for a website explicitly visited by the user, using Rappor.
*/
public static void recordExplicitUserNavigation(String destinationUrl, int rapporMetric) {
switch (rapporMetric) {
case RAPPOR_ACTION_NAVIGATED_USING_OMNIBOX:
RapporServiceBridge.sampleDomainAndRegistryFromURL(
"NTP.ExplicitUserAction.PageNavigation.OmniboxNonSearch", destinationUrl);
return;
case RAPPOR_ACTION_VISITED_SUGGESTED_TILE:
RapporServiceBridge.sampleDomainAndRegistryFromURL(
"NTP.ExplicitUserAction.PageNavigation.NTPTileClick", destinationUrl);
return;
default:
return;
}
}
/**
* Records how content suggestions have been updated in the UI.
* @param result result key, one of {@link ContentSuggestionsUIUpdateResult}'s values.
*/
public static void recordUIUpdateResult(
@ContentSuggestionsUIUpdateResult int result) {
RecordHistogram.recordEnumeratedHistogram("NewTabPage.ContentSuggestions.UIUpdateResult2",
result, ContentSuggestionsUIUpdateResult.NUM_ENTRIES);
}
/**
* Record how many content suggestions have been seen by the user in the UI section before the
* section was successfully updated.
* @param numberOfSuggestionsSeen The number of content suggestions seen so far in the section.
*/
public static void recordNumberOfSuggestionsSeenBeforeUIUpdateSuccess(
int numberOfSuggestionsSeen) {
assert numberOfSuggestionsSeen >= 0;
RecordHistogram.recordCount100Histogram(
"NewTabPage.ContentSuggestions.UIUpdateSuccessNumberOfSuggestionsSeen",
numberOfSuggestionsSeen);
}
/**
* Record a NTP impression (even potential ones to make informed product decisions).
* @param impressionType Type of the impression from NewTabPageUma.java
*/
public static void recordNTPImpression(int impressionType) {
assert impressionType >= 0;
assert impressionType < NUM_NTP_IMPRESSION;
RecordHistogram.recordEnumeratedHistogram(
"Android.NTP.Impression", impressionType, NUM_NTP_IMPRESSION);
}
/**
* Records how often new tabs with a NewTabPage are created. This helps to determine how often
* users navigate back to already opened NTPs.
* @param tabModelSelector Model selector controlling the creation of new tabs.
*/
public static void monitorNTPCreation(TabModelSelector tabModelSelector) {
tabModelSelector.addObserver(new TabCreationRecorder());
}
/**
* Records the type of load for the NTP, such as cold or warm start.
*/
public static void recordLoadType(ChromeActivity activity) {
if (activity.getLastUserInteractionTime() > 0) {
RecordHistogram.recordEnumeratedHistogram(
"NewTabPage.LoadType", LOAD_TYPE_OTHER, LOAD_TYPE_COUNT);
return;
}
if (activity.hadWarmStart()) {
RecordHistogram.recordEnumeratedHistogram(
"NewTabPage.LoadType", LOAD_TYPE_WARM_START, LOAD_TYPE_COUNT);
return;
}
RecordHistogram.recordEnumeratedHistogram(
"NewTabPage.LoadType", LOAD_TYPE_COLD_START, LOAD_TYPE_COUNT);
}
/**
* Records how much time elapsed from start until the search box became available to the user.
*/
public static void recordSearchAvailableLoadTime(ChromeActivity activity) {
// Log the time it took for the search box to be displayed at startup, based on the
// timestamp on the intent for the activity. If the user has interacted with the
// activity already, it's not a startup, and the timestamp on the activity would not be
// relevant either.
if (activity.getLastUserInteractionTime() != 0) return;
long timeFromIntent = SystemClock.elapsedRealtime()
- IntentHandler.getTimestampFromIntent(activity.getIntent());
if (activity.hadWarmStart()) {
RecordHistogram.recordMediumTimesHistogram(
"NewTabPage.SearchAvailableLoadTime2.WarmStart", timeFromIntent,
TimeUnit.MILLISECONDS);
} else {
RecordHistogram.recordMediumTimesHistogram(
"NewTabPage.SearchAvailableLoadTime2.ColdStart", timeFromIntent,
TimeUnit.MILLISECONDS);
}
}
/**
* Records number of prefetched article suggestions, which were available when content
* suggestions surface was opened and there was no network connection.
*/
public static void recordPrefetchedArticleSuggestionsCount(int count) {
RecordHistogram.recordEnumeratedHistogram(
"NewTabPage.ContentSuggestions.CountOnNtpOpenedIfVisible."
+ "Articles.Prefetched.Offline2",
count, MAX_SUGGESTIONS_PER_SECTION);
}
/**
* Records position of a prefetched article suggestion, which was seen by the user on the
* suggestions surface when there was no network connection.
*/
public static void recordPrefetchedArticleSuggestionImpressionPosition(int positionInSection) {
RecordHistogram.recordEnumeratedHistogram("NewTabPage.ContentSuggestions.Shown.Articles."
+ "Prefetched.Offline2",
positionInSection, MAX_SUGGESTIONS_PER_SECTION);
}
/**
* Records the number of new NTPs opened in a new tab. Use through
* {@link NewTabPageUma#monitorNTPCreation(TabModelSelector)}.
*/
private static class TabCreationRecorder extends EmptyTabModelSelectorObserver {
@Override
public void onNewTabCreated(Tab tab) {
if (!NewTabPage.isNTPUrl(tab.getUrl())) return;
RecordUserAction.record("MobileNTPOpenedInNewTab");
}
}
}