Index: chrome/android/java_staging/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java |
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java |
deleted file mode 100644 |
index bbbb36aa26f11a06510f5bc43df0a7775190c938..0000000000000000000000000000000000000000 |
--- a/chrome/android/java_staging/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java |
+++ /dev/null |
@@ -1,394 +0,0 @@ |
-// 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.contextualsearch; |
- |
-import android.content.Context; |
- |
-import org.chromium.base.VisibleForTesting; |
-import org.chromium.chrome.browser.ChromeVersionInfo; |
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType; |
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager; |
-import org.chromium.chrome.browser.preferences.NetworkPredictionOptions; |
-import org.chromium.chrome.browser.preferences.PrefServiceBridge; |
-import org.chromium.content.browser.ContentViewCore; |
- |
-import java.net.URL; |
-import java.util.regex.Pattern; |
- |
-import javax.annotation.Nullable; |
- |
- |
-/** |
- * Handles policy decisions for the {@code ContextualSearchManager}. |
- */ |
-class ContextualSearchPolicy { |
- private static final Pattern CONTAINS_WHITESPACE_PATTERN = Pattern.compile("\\s"); |
- private static final int REMAINING_NOT_APPLICABLE = -1; |
- |
- private static ContextualSearchPolicy sInstance; |
- |
- private final ChromePreferenceManager mPreferenceManager; |
- |
- // Members used only for testing purposes. |
- private boolean mDidOverrideDecidedStateForTesting; |
- private boolean mDecidedStateForTesting; |
- private boolean mDidResetCounters; |
- |
- static ContextualSearchPolicy getInstance(Context context) { |
- if (sInstance == null) { |
- sInstance = new ContextualSearchPolicy(context); |
- } |
- return sInstance; |
- } |
- |
- /** |
- * Private constructor -- use {@link #getInstance} to get the singleton instance. |
- * @param context The Android Context. |
- */ |
- private ContextualSearchPolicy(Context context) { |
- mPreferenceManager = ChromePreferenceManager.getInstance(context); |
- } |
- |
- // TODO(donnd): Consider adding a test-only constructor that uses dependency injection of a |
- // preference manager and PrefServiceBridge. Currently this is not possible because the |
- // PrefServiceBridge is final. |
- |
- /** |
- * @return The number of additional times to show the promo on tap, 0 if it should not be shown, |
- * or a negative value if the counter has been disabled or the user has accepted |
- * the promo. |
- */ |
- int getPromoTapsRemaining() { |
- if (!isUserUndecided()) return REMAINING_NOT_APPLICABLE; |
- |
- // Return a non-negative value if opt-out promo counter is enabled, and there's a limit. |
- DisableablePromoTapCounter counter = getPromoTapCounter(); |
- if (counter.isEnabled()) { |
- int limit = ContextualSearchFieldTrial.getPromoTapTriggeredLimit(); |
- if (limit >= 0) return Math.max(0, limit - counter.getCount()); |
- } |
- |
- return REMAINING_NOT_APPLICABLE; |
- } |
- |
- /** |
- * @return the {@link DisableablePromoTapCounter}. |
- */ |
- DisableablePromoTapCounter getPromoTapCounter() { |
- return DisableablePromoTapCounter.getInstance(mPreferenceManager); |
- } |
- |
- /** |
- * @return Whether a Tap gesture is currently supported as a trigger for the feature. |
- */ |
- boolean isTapSupported() { |
- if (!isUserUndecided()) return true; |
- |
- if (ContextualSearchFieldTrial.isPromoLongpressTriggeredOnly()) return false; |
- |
- return !ContextualSearchFieldTrial.isPromoLimitedByTapCounts() |
- || getPromoTapsRemaining() != 0; |
- } |
- |
- /** |
- * @return whether or not the Contextual Search Result should be preloaded before the user |
- * explicitly interacts with the feature. |
- */ |
- boolean shouldPrefetchSearchResult(boolean isTapTriggered) { |
- if (PrefServiceBridge.getInstance().getNetworkPredictionOptions() |
- == NetworkPredictionOptions.NETWORK_PREDICTION_NEVER) { |
- return false; |
- } |
- |
- if (isTapPrefetchBeyondTheLimit()) return false; |
- |
- // If we're not resolving the tap due to the tap limit, we should not preload either. |
- if (isTapResolveBeyondTheLimit()) return false; |
- |
- // We never preload on long-press so users can cut & paste without hitting the servers. |
- return isTapTriggered; |
- } |
- |
- /** |
- * Returns whether the previous tap (the tap last counted) should resolve. |
- * @return Whether the previous tap should resolve. |
- */ |
- boolean shouldPreviousTapResolve(@Nullable URL url) { |
- if (isTapResolveBeyondTheLimit()) { |
- return false; |
- } |
- |
- if (isPromoAvailable()) { |
- return isBasePageHTTP(url); |
- } |
- |
- return true; |
- } |
- |
- /** |
- * Returns whether surrounding context can be accessed by other systems or not. |
- * @baseContentViewUrl The URL of the base page. |
- * @return Whether surroundings are available. |
- */ |
- boolean canSendSurroundings(@Nullable URL baseContentViewUrl) { |
- if (isUserUndecided()) return false; |
- |
- if (isPromoAvailable()) { |
- return isBasePageHTTP(baseContentViewUrl); |
- } |
- |
- return true; |
- } |
- |
- /** |
- * @return Whether the Opt-out promo is available to be shown in any panel. |
- */ |
- boolean isPromoAvailable() { |
- return isUserUndecided(); |
- } |
- |
- /** |
- * Registers that a tap has taken place by incrementing tap-tracking counters. |
- */ |
- void registerTap() { |
- if (isPromoAvailable()) { |
- DisableablePromoTapCounter promoTapCounter = getPromoTapCounter(); |
- // Bump the counter only when it is still enabled. |
- if (promoTapCounter.isEnabled()) { |
- promoTapCounter.increment(); |
- } |
- } |
- int tapsSinceOpen = mPreferenceManager.getContextualSearchTapCount(); |
- mPreferenceManager.setContextualSearchTapCount(++tapsSinceOpen); |
- if (isUserUndecided()) { |
- ContextualSearchUma.logTapsSinceOpenForUndecided(tapsSinceOpen); |
- } else { |
- ContextualSearchUma.logTapsSinceOpenForDecided(tapsSinceOpen); |
- } |
- } |
- |
- /** |
- * Updates all the counters to account for an open-action on the panel. |
- */ |
- void updateCountersForOpen() { |
- // Always completely reset the tap counter, since it just counts taps |
- // since the last open. |
- mPreferenceManager.setContextualSearchTapCount(0); |
- |
- // Disable the "promo tap" counter, but only if we're using the Opt-out onboarding. |
- // For Opt-in, we never disable the promo tap counter. |
- if (isPromoAvailable()) { |
- getPromoTapCounter().disable(); |
- |
- // Bump the total-promo-opens counter. |
- int count = mPreferenceManager.getContextualSearchPromoOpenCount(); |
- mPreferenceManager.setContextualSearchPromoOpenCount(++count); |
- ContextualSearchUma.logPromoOpenCount(count); |
- } |
- } |
- |
- /** |
- * @return Whether a verbatim request should be made for the given base page, assuming there |
- * is no exiting request. |
- */ |
- boolean shouldCreateVerbatimRequest(ContextualSearchSelectionController controller, |
- @Nullable URL basePageUrl) { |
- // TODO(donnd): refactor to make the controller a member of this class? |
- return (controller.getSelectedText() != null |
- && (controller.getSelectionType() == SelectionType.LONG_PRESS |
- || (controller.getSelectionType() == SelectionType.TAP |
- && !shouldPreviousTapResolve(basePageUrl)))); |
- } |
- |
- /** |
- * Determines whether an error from a search term resolution request should |
- * be shown to the user, or not. |
- */ |
- boolean shouldShowErrorCodeInBar() { |
- // Builds with lots of real users should not see raw error codes. |
- return !(ChromeVersionInfo.isStableBuild() || ChromeVersionInfo.isBetaBuild()); |
- } |
- |
- /** |
- * Logs the current user's state, including preference, tap and open counters, etc. |
- */ |
- void logCurrentState(@Nullable ContentViewCore cvc) { |
- if (cvc == null || !ContextualSearchFieldTrial.isEnabled( |
- cvc.getContext().getApplicationContext())) { |
- return; |
- } |
- |
- ContextualSearchUma.logPreferenceState(); |
- |
- // Log the number of promo taps remaining. |
- int promoTapsRemaining = getPromoTapsRemaining(); |
- if (promoTapsRemaining >= 0) ContextualSearchUma.logPromoTapsRemaining(promoTapsRemaining); |
- |
- // Also log the total number of taps before opening the promo, even for those |
- // that are no longer tap limited. That way we'll know the distribution of the |
- // number of taps needed before opening the promo. |
- DisableablePromoTapCounter promoTapCounter = getPromoTapCounter(); |
- boolean wasOpened = !promoTapCounter.isEnabled(); |
- int count = promoTapCounter.getCount(); |
- if (wasOpened) { |
- ContextualSearchUma.logPromoTapsBeforeFirstOpen(count); |
- } else { |
- ContextualSearchUma.logPromoTapsForNeverOpened(count); |
- } |
- } |
- |
- /** |
- * Logs details about the Search Term Resolution. |
- * Should only be called when a search term has been resolved. |
- * @param searchTerm The Resolved Search Term. |
- * @param basePageUrl The URL of the base page. |
- */ |
- void logSearchTermResolutionDetails(String searchTerm, @Nullable URL basePageUrl) { |
- // Only log for decided users so the data reflect fully-enabled behavior. |
- // Otherwise we'll get skewed data; more HTTP pages than HTTPS (since those don't resolve), |
- // and it's also possible that public pages, e.g. news, have more searches for multi-word |
- // entities like people. |
- if (!isUserUndecided()) { |
- ContextualSearchUma.logBasePageProtocol(isBasePageHTTP(basePageUrl)); |
- boolean isSingleWord = !CONTAINS_WHITESPACE_PATTERN.matcher(searchTerm.trim()).find(); |
- ContextualSearchUma.logSearchTermResolvedWords(isSingleWord); |
- } |
- } |
- |
- /** |
- * Whether sending the URL of the base page to the server may be done for policy reasons. |
- * NOTE: There may be additional privacy reasons why the base page URL should not be sent. |
- * TODO(donnd): Update this API to definitively determine if it's OK to send the URL, |
- * by merging the checks in the native contextual_search_delegate here. |
- * @return {@code true} if the URL may be sent for policy reasons. |
- * Note that a return value of {@code true} may still require additional checks |
- * to see if all privacy-related conditions are met to send the base page URL. |
- */ |
- boolean maySendBasePageUrl() { |
- return !isUserUndecided(); |
- } |
- |
- // -------------------------------------------------------------------------------------------- |
- // Testing support. |
- // -------------------------------------------------------------------------------------------- |
- |
- /** |
- * Resets all policy counters. |
- */ |
- @VisibleForTesting |
- void resetCounters() { |
- updateCountersForOpen(); |
- |
- mPreferenceManager.setContextualSearchPromoOpenCount(0); |
- mDidResetCounters = true; |
- } |
- |
- /** |
- * Overrides the decided/undecided state for the user preference. |
- * @param decidedState Whether the user has decided or not. |
- */ |
- @VisibleForTesting |
- void overrideDecidedStateForTesting(boolean decidedState) { |
- mDidOverrideDecidedStateForTesting = true; |
- mDecidedStateForTesting = decidedState; |
- } |
- |
- /** |
- * @return Whether counters have been reset yet (by resetCounters) or not. |
- */ |
- @VisibleForTesting |
- boolean didResetCounters() { |
- return mDidResetCounters; |
- } |
- |
- /** |
- * @return count of times the panel with the promo has been opened. |
- */ |
- @VisibleForTesting |
- int getPromoOpenCount() { |
- return mPreferenceManager.getContextualSearchPromoOpenCount(); |
- } |
- |
- /** |
- * @return The number of times the user has tapped since the last panel open. |
- */ |
- @VisibleForTesting |
- int getTapCount() { |
- return mPreferenceManager.getContextualSearchTapCount(); |
- } |
- |
- // -------------------------------------------------------------------------------------------- |
- // Private helpers. |
- // -------------------------------------------------------------------------------------------- |
- |
- /** |
- * @return Whether a promo is needed because the user is still undecided |
- * on enabling or disabling the feature. |
- */ |
- private boolean isUserUndecided() { |
- // TODO(donnd) use dependency injection for the PrefServiceBridge instead! |
- if (mDidOverrideDecidedStateForTesting) return !mDecidedStateForTesting; |
- |
- return PrefServiceBridge.getInstance().isContextualSearchUninitialized(); |
- } |
- |
- /** |
- * @param url The URL of the base page. |
- * @return Whether the given content view is for an HTTP page. |
- */ |
- private boolean isBasePageHTTP(@Nullable URL url) { |
- return url != null && "http".equals(url.getProtocol()); |
- } |
- |
- /** |
- * @return Whether the tap resolve limit has been exceeded. |
- */ |
- private boolean isTapResolveBeyondTheLimit() { |
- return isTapResolveLimited() && getTapCount() > getTapResolveLimit(); |
- } |
- |
- /** |
- * @return Whether the tap resolve limit has been exceeded. |
- */ |
- private boolean isTapPrefetchBeyondTheLimit() { |
- return isTapPrefetchLimited() && getTapCount() > getTapPrefetchLimit(); |
- } |
- |
- /** |
- * @return Whether a tap gesture is resolve-limited. |
- */ |
- private boolean isTapResolveLimited() { |
- return isUserUndecided() |
- ? ContextualSearchFieldTrial.isTapResolveLimitedForUndecided() |
- : ContextualSearchFieldTrial.isTapResolveLimitedForDecided(); |
- } |
- |
- /** |
- * @return Whether a tap gesture is resolve-limited. |
- */ |
- private boolean isTapPrefetchLimited() { |
- return isUserUndecided() |
- ? ContextualSearchFieldTrial.isTapPrefetchLimitedForUndecided() |
- : ContextualSearchFieldTrial.isTapPrefetchLimitedForDecided(); |
- } |
- |
- /** |
- * @return The limit of the number of taps to prefetch. |
- */ |
- private int getTapPrefetchLimit() { |
- return isUserUndecided() |
- ? ContextualSearchFieldTrial.getTapPrefetchLimitForUndecided() |
- : ContextualSearchFieldTrial.getTapPrefetchLimitForDecided(); |
- } |
- |
- /** |
- * @return The limit of the number of taps to resolve using search term resolution. |
- */ |
- private int getTapResolveLimit() { |
- return isUserUndecided() |
- ? ContextualSearchFieldTrial.getTapResolveLimitForUndecided() |
- : ContextualSearchFieldTrial.getTapResolveLimitForDecided(); |
- } |
-} |