// Copyright 2015 The Chromium Authors
// 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.contextualsearch;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Pair;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
import org.chromium.chrome.browser.contextualsearch.ResolvedSearchTerm.CardTag;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridge;
import org.chromium.chrome.browser.sync.SyncServiceFactory;
import org.chromium.components.sync.SyncService;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Centralizes UMA data collection for Contextual Search. All calls must be made from the UI thread.
*/
public class ContextualSearchUma {
// Constants to use for the original selection gesture
private static final boolean LONG_PRESS = false;
private static final boolean TAP = true;
/** A pattern to determine if text contains any whitespace. */
private static final Pattern CONTAINS_WHITESPACE_PATTERN = Pattern.compile("\\s");
// Constants with ContextualSearchPreferenceState in enums.xml.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
@IntDef({
ContextualSearchPreference.UNINITIALIZED,
ContextualSearchPreference.ENABLED,
ContextualSearchPreference.DISABLED
})
@Retention(RetentionPolicy.SOURCE)
public @interface ContextualSearchPreference {
int UNINITIALIZED = 0;
int ENABLED = 1;
int DISABLED = 2;
int NUM_ENTRIES = 3;
}
// Constants used to log UMA "enum" histograms about whether search results were seen.
@IntDef({Results.SEEN, Results.NOT_SEEN})
@Retention(RetentionPolicy.SOURCE)
private @interface Results {
int SEEN = 0;
int NOT_SEEN = 1;
int NUM_ENTRIES = 2;
}
// Constants used to log UMA "enum" histograms with details about whether search results
// were seen, and what the original triggering gesture was.
@IntDef({
ResultsByGesture.SEEN_FROM_TAP,
ResultsByGesture.NOT_SEEN_FROM_TAP,
ResultsByGesture.SEEN_FROM_LONG_PRESS,
ResultsByGesture.NOT_SEEN_FROM_LONG_PRESS
})
@Retention(RetentionPolicy.SOURCE)
private @interface ResultsByGesture {
int SEEN_FROM_TAP = 0;
int NOT_SEEN_FROM_TAP = 1;
int SEEN_FROM_LONG_PRESS = 2;
int NOT_SEEN_FROM_LONG_PRESS = 3;
int NUM_ENTRIES = 4;
}
// Constants for quick action intent resolution histogram.
@IntDef({QuickActionResolve.FAILED, QuickActionResolve.SINGLE, QuickActionResolve.MULTIPLE})
@Retention(RetentionPolicy.SOURCE)
private @interface QuickActionResolve {
int FAILED = 0;
int SINGLE = 1;
int MULTIPLE = 2;
int NUM_ENTRIES = 3;
}
// Enums for the Counted.Event histogram designed to match the Rasta queries(event) metric.
@IntDef({
CountedEvent.UNINTELLIGENT_COUNTED,
CountedEvent.INTELLIGENT_COUNTED,
CountedEvent.INTELLIGENT_NOT_COUNTED,
CountedEvent.NUM_ENTRIES
})
@Retention(RetentionPolicy.SOURCE)
private @interface CountedEvent {
int UNINTELLIGENT_COUNTED = 0;
int INTELLIGENT_COUNTED = 1;
int INTELLIGENT_NOT_COUNTED = 2;
int NUM_ENTRIES = 3;
}
/** Key used in maps from {state, reason} to state entry (exit) logging code. */
static class StateChangeKey {
final @PanelState int mState;
final @StateChangeReason int mReason;
final int mHashCode;
StateChangeKey(@PanelState int state, @StateChangeReason int reason) {
mState = state;
mReason = reason;
mHashCode = 31 * state + reason;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof StateChangeKey)) return false;
if (obj == this) return true;
StateChangeKey other = (StateChangeKey) obj;
return mState == other.mState && mReason == other.mReason;
}
@Override
public int hashCode() {
return mHashCode;
}
}
// TODO(donnd): switch from using Maps to some method that does not require creation of a key.
// "Seen by gesture" code map: logged on first exit from expanded panel, or promo,
// broken down by gesture.
private static final Map<Pair<Boolean, Boolean>, Integer> SEEN_BY_GESTURE_CODES;
static {
final boolean unseen = false;
final boolean seen = true;
Map<Pair<Boolean, Boolean>, Integer> codes = new HashMap<Pair<Boolean, Boolean>, Integer>();
codes.put(new Pair<Boolean, Boolean>(seen, TAP), ResultsByGesture.SEEN_FROM_TAP);
codes.put(new Pair<Boolean, Boolean>(unseen, TAP), ResultsByGesture.NOT_SEEN_FROM_TAP);
codes.put(
new Pair<Boolean, Boolean>(seen, LONG_PRESS),
ResultsByGesture.SEEN_FROM_LONG_PRESS);
codes.put(
new Pair<Boolean, Boolean>(unseen, LONG_PRESS),
ResultsByGesture.NOT_SEEN_FROM_LONG_PRESS);
SEEN_BY_GESTURE_CODES = Collections.unmodifiableMap(codes);
}
/**
* Logs the state of the Contextual Search preference. This function should be called if the
* Contextual Search feature is active, and will track the different preference settings
* (disabled, enabled or uninitialized). Calling more than once is fine.
*/
public static void logPreferenceState(Profile profile) {
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearchPreferenceState",
getPreferenceValue(profile),
ContextualSearchPreference.NUM_ENTRIES);
}
/**
* Records the total count of times the revised promo card has *ever* been opened. This should
* only be called when the user is still undecided.
* @param count The total historic count of times the revised promo card ever been shown.
*/
public static void logRevisedPromoOpenCount(int count) {
RecordHistogram.recordCount1MHistogram("Search.ContextualSearchPromoOpenCount2", count);
}
/**
* Logs changes to the Contextual Search preference, aside from those resulting from the first
* run flow.
* @param enabled Whether the preference is being enabled or disabled.
*/
public static void logMainPreferenceChange(boolean enabled) {
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearchPreferenceStateChange",
enabled ? ContextualSearchPreference.ENABLED : ContextualSearchPreference.DISABLED,
ContextualSearchPreference.NUM_ENTRIES);
}
/**
* Logs changes to the Contextual Search privacy opt-in preference.
* @param enabled Whether the opt-in preference is being enabled or disabled.
*/
public static void logPrivacyOptInPreferenceChange(boolean enabled) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearchPrivacyOptInPreferenceStateChange", enabled);
}
/**
* Logs the user's choice for the Contextual Search Promo Card.
* @param enabled Whether the opt-in to full privacy is being chosen.
*/
public static void logPromoCardChoice(boolean enabled) {
RecordHistogram.recordBooleanHistogram("Search.ContextualSearchPromoCardChoice", enabled);
}
/**
* Logs a user action for the duration of viewing the panel that describes the amount of time
* the user viewed the bar and panel overall.
* @param durationMs The duration to record.
*/
public static void logPanelViewDurationAction(long durationMs) {
if (durationMs < DateUtils.SECOND_IN_MILLIS) {
RecordUserAction.record("ContextualSearch.ViewLessThanOneSecond");
} else if (durationMs < DateUtils.SECOND_IN_MILLIS * 3) {
RecordUserAction.record("ContextualSearch.ViewOneToThreeSeconds");
} else if (durationMs < DateUtils.SECOND_IN_MILLIS * 10) {
RecordUserAction.record("ContextualSearch.ViewThreeToTenSeconds");
} else {
RecordUserAction.record("ContextualSearch.ViewMoreThanTenSeconds");
}
}
/**
* Logs whether search results were seen.
* Logs multiple histograms; with and without the original triggering gesture.
* @param wasPanelSeen Whether the panel was seen.
* @param wasTap Whether the gesture that originally caused the panel to show was a Tap.
*/
public static void logResultsSeen(boolean wasPanelSeen, boolean wasTap) {
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearchResultsSeen",
wasPanelSeen ? Results.SEEN : Results.NOT_SEEN,
Results.NUM_ENTRIES);
logHistogramByGesture(wasPanelSeen, wasTap, "Search.ContextualSearchResultsSeenByGesture");
}
/**
* Logs whether search results were seen for a Tap gesture, for all users and sync-enabled
* users. For users that have UKM enabled we log to a separate histogram in order to help
* validate the Ranker Tap Suppression model results (since they are trained on UKM data).
*
* @param wasPanelSeen Whether the panel was seen.
* @param profile The current {@link Profile}.
*/
public static void logTapResultsSeen(boolean wasPanelSeen, Profile profile) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.Tap.ResultsSeen", wasPanelSeen);
if (ChromeFeatureList.isEnabled(
ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)) {
if (UnifiedConsentServiceBridge.isUrlKeyedAnonymizedDataCollectionEnabled(profile)) {
// The histogram has SyncEnabled in the name, since this is what it was using in the
// past instead of checking the UKM state directly.
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.Tap.SyncEnabled.ResultsSeen", wasPanelSeen);
}
return;
}
@Nullable SyncService syncService = SyncServiceFactory.getForProfile(profile);
if (syncService != null && syncService.isSyncFeatureEnabled()) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.Tap.SyncEnabled.ResultsSeen", wasPanelSeen);
}
}
/**
* Logs whether search results were seen for all gestures. Recorded for all users.
* @param wasPanelSeen Whether the panel was seen.
*/
public static void logAllResultsSeen(boolean wasPanelSeen) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.All.ResultsSeen", wasPanelSeen);
// Log a user action for the wasPanelSeen case. This value is used as part of a high-level
// guiding metric, which is being migrated to user actions.
if (wasPanelSeen) {
RecordUserAction.record("Search.ContextualSearch.All.ResultsSeen.true");
}
}
/**
* Logs all searches that were displayed to the user in a Search Result Page in the panel.
* @param wasRelatedSearches Whether the search was due to Related Searches (as opposed to
* being a regular Contextual Search query).
*/
public static void logAllSearches(boolean wasRelatedSearches) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.All.Searches", wasRelatedSearches);
}
/**
* Logs histograms designed to match the Rasta queries(event) metric.
* One histogram summarizes all triggering of this feature and whether they were counted or not.
* Another histogram breaks down the cases where the panel was opened by what kind of search it
* was and whether it was counted by Rasta.
* The intent is to filter out very brief opens of the panel in which the SRP did not load in
* time for the user to see it or for Rasta to count it. In particular the Contextual Search
* dynamic JavaScript that converts a prefetch into a real search needs to have loaded and
* executed to count prefetch conversions as Searches in Rasta.
* @param wasPanelSeen Whether the panel was opened beyond the peeking state.
* @param wasDocumentPainted Whether the document was actually starting to render in the Content
* View so the user could actually see it.
* @param wasPrefetch Whether the Search was a prefetch generated by an intelligent search.
*/
public static void logCountedSearches(
boolean wasPanelSeen, boolean wasDocumentPainted, boolean wasPrefetch) {
// Get the enum for the category for those seen, and record the category of the search.
// Default to the simplest Counted enum, which is useful for both histograms.
@CountedEvent int searchEnum = CountedEvent.UNINTELLIGENT_COUNTED;
if (wasPanelSeen) {
// Prefetch indicates an intelligent search and might not have been counted through
// dynamic JavaScript conversion.
if (wasPrefetch) {
searchEnum =
wasDocumentPainted
? CountedEvent.INTELLIGENT_COUNTED
: CountedEvent.INTELLIGENT_NOT_COUNTED;
}
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearch.Counted.Event", searchEnum, CountedEvent.NUM_ENTRIES);
}
boolean wasSeenAndCounted =
wasPanelSeen && searchEnum != CountedEvent.INTELLIGENT_NOT_COUNTED;
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.Counted.Searches", wasSeenAndCounted);
}
/**
* Logs a User Action for promoting the Overlay into it's own separate Tab.
* @param isShowingRelatedSearchSerp Whether the current SERP shown in the Overlay is from
* Related Searches or not (just a plain Contextual Search).
*/
public static void logTabPromotion(boolean isShowingRelatedSearchSerp) {
if (isShowingRelatedSearchSerp) {
RecordUserAction.record("RelatedSearches.TabPromotion");
} else {
RecordUserAction.record("ContextualSearch.TabPromotion");
}
}
/**
* Logs a User Action for clicking on a search result in the Search Result Page.
* @param isShowingRelatedSearchSerp Whether the current SERP shown in the Overlay is from
* Related Searches or not (just a plain Contextual Search).
*/
public static void logSerpResultClicked(boolean isShowingRelatedSearchSerp) {
if (isShowingRelatedSearchSerp) {
RecordUserAction.record("RelatedSearches.SerpResultClicked");
} else {
RecordUserAction.record("ContextualSearch.SerpResultClicked");
}
}
/**
* Logs a user action for a change to the Panel state, which allows sequencing of actions.
* @param toState The state to transition to.
* @param reason The reason for the state transition.
*/
public static void logPanelStateUserAction(
@PanelState int toState, @StateChangeReason int reason) {
switch (toState) {
case PanelState.CLOSED:
if (reason == StateChangeReason.BACK_PRESS) {
RecordUserAction.record("ContextualSearch.BackPressClose");
} else if (reason == StateChangeReason.CLOSE_BUTTON) {
RecordUserAction.record("ContextualSearch.CloseButtonClose");
} else if (reason == StateChangeReason.SWIPE || reason == StateChangeReason.FLING) {
RecordUserAction.record("ContextualSearch.SwipeOrFlingClose");
} else if (reason == StateChangeReason.TAB_PROMOTION) {
RecordUserAction.record("ContextualSearch.TabPromotionClose");
} else if (reason == StateChangeReason.BASE_PAGE_TAP) {
RecordUserAction.record("ContextualSearch.BasePageTapClose");
} else if (reason == StateChangeReason.BASE_PAGE_SCROLL) {
RecordUserAction.record("ContextualSearch.BasePageScrollClose");
} else if (reason == StateChangeReason.SEARCH_BAR_TAP) {
RecordUserAction.record("ContextualSearch.SearchBarTapClose");
} else if (reason == StateChangeReason.SERP_NAVIGATION) {
RecordUserAction.record("ContextualSearch.NavigationClose");
} else {
RecordUserAction.record("ContextualSearch.UncommonClose");
}
break;
case PanelState.PEEKED:
if (reason == StateChangeReason.TEXT_SELECT_TAP) {
RecordUserAction.record("ContextualSearch.TapPeek");
} else if (reason == StateChangeReason.SWIPE || reason == StateChangeReason.FLING) {
RecordUserAction.record("ContextualSearch.SwipeOrFlingPeek");
} else if (reason == StateChangeReason.TEXT_SELECT_LONG_PRESS) {
RecordUserAction.record("ContextualSearch.LongpressPeek");
}
break;
case PanelState.EXPANDED:
if (reason == StateChangeReason.SWIPE || reason == StateChangeReason.FLING) {
RecordUserAction.record("ContextualSearch.SwipeOrFlingExpand");
} else if (reason == StateChangeReason.SEARCH_BAR_TAP) {
RecordUserAction.record("ContextualSearch.SearchBarTapExpand");
}
break;
case PanelState.MAXIMIZED:
if (reason == StateChangeReason.SWIPE || reason == StateChangeReason.FLING) {
RecordUserAction.record("ContextualSearch.SwipeOrFlingMaximize");
} else if (reason == StateChangeReason.SERP_NAVIGATION) {
RecordUserAction.record("ContextualSearch.NavigationMaximize");
}
break;
default:
break;
}
}
/** Logs that the user established a new selection when Contextual Search is active. */
public static void logSelectionEstablished() {
RecordUserAction.record("ContextualSearch.SelectionEstablished");
}
/**
* Logs that the user manually adjusted a selection when Contextual Search is active.
* @param selection The new selection.
*/
public static void logSelectionAdjusted(@Nullable String selection) {
if (TextUtils.isEmpty(selection)) return;
boolean isSingleWord = !CONTAINS_WHITESPACE_PATTERN.matcher(selection.trim()).find();
if (isSingleWord) {
RecordUserAction.record("ContextualSearch.ManualRefineSingleWord");
} else {
RecordUserAction.record("ContextualSearch.ManualRefineMultiWord");
}
}
/** Logs a UserAction that the user just acknowledged the Longpress in-panel-help. */
static void logInPanelHelpAcknowledged() {
RecordUserAction.record("ContextualSearch.logInPanelHelpAcknowledged");
}
/**
* Logs that the system automatically expanded the selection when a user triggered
* Contextual Search on a multiword phrase that could be identified by the server.
* @param fromTapGesture Whether the gesture that originally established the selection
* was Tap.
*/
public static void logSelectionExpanded(boolean fromTapGesture) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.SelectionExpanded", fromTapGesture);
}
/**
* Logs that the system sent a server request to resolve the search term.
* @param fromTapGesture Whether the gesture that originally established the selection
* was Tap.
*/
public static void logResolveRequested(boolean fromTapGesture) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.ResolveRequested", fromTapGesture);
}
/**
* Logs that the system received a server response from a resolve request.
* @param fromTapGesture Whether the gesture that originally established the selection
* was Tap.
*/
public static void logResolveReceived(boolean fromTapGesture) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.ResolveReceived", fromTapGesture);
}
/**
* Logs whether Contextual Cards data was shown. Should be logged on tap if Contextual
* Cards integration is enabled.
* @param shown Whether Contextual Cards data was shown in the Bar.
*/
public static void logContextualCardsDataShown(boolean shown) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearchContextualCardsIntegration.DataShown", shown);
}
/**
* Logs whether a quick action intent resolved to zero, one, or many apps.
* @param quickActionCategory The {@link QuickActionCategory} for the quick action.
* @param numMatchingAppsApps The number of apps that the resolved intent matched.
*/
public static void logQuickActionIntentResolution(
int quickActionCategory, int numMatchingAppsApps) {
int code =
numMatchingAppsApps == 0
? QuickActionResolve.FAILED
: numMatchingAppsApps == 1
? QuickActionResolve.SINGLE
: QuickActionResolve.MULTIPLE;
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearchQuickActions.IntentResolution."
+ getLabelForQuickActionCategory(quickActionCategory),
code,
QuickActionResolve.NUM_ENTRIES);
}
/**
* Logs whether a quick action was shown, and the quick aciton category if a quick action was
* shown. Should be logged on tap if Contextual Search single actions are enabled.
* @param quickActionShown Whether a quick action was shown.
* @param quickActionCategory The {@link QuickActionCategory} for the quick action.
*/
public static void logQuickActionShown(boolean quickActionShown, int quickActionCategory) {
if (quickActionShown) {
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearchQuickActions.Category",
quickActionCategory,
QuickActionCategory.BOUNDARY);
}
}
/**
* Logs whether results were seen when a quick action was present.
* @param wasSeen Whether the search results were seen.
* @param quickActionCategory The {@link QuickActionCategory} for the quick action.
*/
public static void logQuickActionResultsSeen(boolean wasSeen, int quickActionCategory) {
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearchQuickActions.ResultsSeen."
+ getLabelForQuickActionCategory(quickActionCategory),
wasSeen ? Results.SEEN : Results.NOT_SEEN,
Results.NUM_ENTRIES);
}
/**
* Logs whether a quick action was clicked.
* @param wasClicked Whether the quick action was clicked
* @param quickActionCategory The {@link QuickActionCategory} for the quick action.
*/
public static void logQuickActionClicked(boolean wasClicked, int quickActionCategory) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearchQuickActions.Clicked."
+ getLabelForQuickActionCategory(quickActionCategory),
wasClicked);
}
/**
* Logs the primary CoCa {@link CardTag} for searches where the panel contents was seen,
* including {@codeCardTag.CT_NONE} when no card or tag, and {@codeCardTag.CT_OTHER} when it's
* one we do not recognize.
* @param wasSearchContentViewSeen Whether the panel was seen.
* @param cardTagEnum The primary CoCa card Tag for the result seen.
*/
public static void logCardTagSeen(boolean wasSearchContentViewSeen, @CardTag int cardTagEnum) {
if (wasSearchContentViewSeen) {
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearch.CardTagSeen", cardTagEnum, CardTag.NUM_ENTRIES);
}
RecordHistogram.recordEnumeratedHistogram(
"Search.ContextualSearch.CardTag", cardTagEnum, CardTag.NUM_ENTRIES);
}
/**
* Logs the previous enabled-state of this user before the feature was turned full-on for
* Unified Consent (when integration is enabled).
* @param wasPreviouslyUndecided Whether the user was previously undecided.
*/
static void logUnifiedConsentPreviousEnabledState(boolean wasPreviouslyUndecided) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.UnifiedConsent.PreviouslyUndecided",
wasPreviouslyUndecided);
}
/**
* Logs whether a request will be throttled for Unified Consent integration, for all requests
* regardless of whether the integration feature is enabled. Logged multiple times per request.
* @param isRequestThrottled Whether the current request is being throttled.
*/
static void logUnifiedConsentThrottledRequests(boolean isRequestThrottled) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.UnifiedConsent.ThrottledRequests", isRequestThrottled);
}
/**
* Logs whether this user was eligible for throttling of requests when Unified Consent
* integration is enabled and throttling is in effect.
* @param isThrottleEligible Whether this user is eligible to be throttled.
*/
static void logUnifiedConsentThrottleEligible(boolean isThrottleEligible) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.UnifiedConsent.ThrottleEligible", isThrottleEligible);
}
/** Logs whether the triggering was suppressed due to the Base Page view being too small. */
static void logViewTooSmall(boolean isViewTooSmall) {
RecordHistogram.recordBooleanHistogram(
"Search.ContextualSearch.SuppressedViewTooSmall", isViewTooSmall);
}
/**
* Gets the panel-seen code for the given parameters by doing a lookup in the seen-by-gesture
* map.
* @param wasPanelSeen Whether the panel was seen.
* @param wasTap Whether the gesture that originally caused the panel to show was a Tap.
* @return The code to write into a panel-seen histogram.
*/
private static int getPanelSeenByGestureStateCode(boolean wasPanelSeen, boolean wasTap) {
return SEEN_BY_GESTURE_CODES.get(new Pair<Boolean, Boolean>(wasPanelSeen, wasTap));
}
/**
* @return The code for the Contextual Search preference.
*/
private static int getPreferenceValue(Profile profile) {
if (ContextualSearchPolicy.isContextualSearchUninitialized(profile)) {
return ContextualSearchPreference.UNINITIALIZED;
} else if (ContextualSearchPolicy.isContextualSearchDisabled(profile)) {
return ContextualSearchPreference.DISABLED;
}
return ContextualSearchPreference.ENABLED;
}
/**
* Logs to a seen-by-gesture histogram of the given name.
* @param wasPanelSeen Whether the panel was seen.
* @param wasTap Whether the gesture that originally caused the panel to show was a Tap.
* @param histogramName The full name of the histogram to log to.
*/
private static void logHistogramByGesture(
boolean wasPanelSeen, boolean wasTap, String histogramName) {
RecordHistogram.recordEnumeratedHistogram(
histogramName,
getPanelSeenByGestureStateCode(wasPanelSeen, wasTap),
ResultsByGesture.NUM_ENTRIES);
}
private static String getLabelForQuickActionCategory(int quickActionCategory) {
switch (quickActionCategory) {
case QuickActionCategory.ADDRESS:
return "Address";
case QuickActionCategory.EMAIL:
return "Email";
case QuickActionCategory.EVENT:
return "Event";
case QuickActionCategory.PHONE:
return "Phone";
case QuickActionCategory.WEBSITE:
return "Website";
default:
return "None";
}
}
}