OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.contextualsearch; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.text.TextUtils; |
| 9 |
| 10 import org.chromium.base.CommandLine; |
| 11 import org.chromium.base.SysUtils; |
| 12 import org.chromium.chrome.browser.ChromeSwitches; |
| 13 import org.chromium.chrome.browser.ChromeVersionInfo; |
| 14 import org.chromium.components.variations.VariationsAssociatedData; |
| 15 import org.chromium.ui.base.DeviceFormFactor; |
| 16 |
| 17 import java.util.Arrays; |
| 18 import java.util.Locale; |
| 19 |
| 20 /** |
| 21 * Provides Field Trial support for the Contextual Search application within Chr
ome for Android. |
| 22 */ |
| 23 public class ContextualSearchFieldTrial { |
| 24 |
| 25 private static final String CONTEXTUAL_SEARCH_FIELD_TRIAL_NAME = "Contextual
Search"; |
| 26 private static final String CONTEXTUAL_SEARCH_ENABLED_PARAM = "enabled"; |
| 27 private static final String CONTEXTUAL_SEARCH_ENABLED_VALUE = "true"; |
| 28 private static final String CONTEXTUAL_SEARCH_DISABLE_FOR_CJK = "disable_for
_cjk"; |
| 29 private static final String CONTEXTUAL_SEARCH_DISABLE_FOR_NON_ENGLISH = |
| 30 "disable_for_non_english"; |
| 31 private static final String CONTEXTUAL_SEARCH_DISABLE_SURROUNDINGS_OBSERVERS
= |
| 32 "disable_surroundings_observers"; |
| 33 private static final String CONTEXTUAL_SEARCH_PROMO_ON_LONGPRESS_ONLY = |
| 34 "promo_on_longpress_only"; |
| 35 static final String CONTEXTUAL_SEARCH_PROMO_ON_LIMITED_TAPS = |
| 36 "promo_on_limited_taps"; |
| 37 static final String CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_LIMIT = |
| 38 "tap_triggered_promo_limit"; |
| 39 private static final String CONTEXTUAL_SEARCH_NAVIGATION_DETECTION_DELAY = |
| 40 "tap_navigation_detection_delay"; |
| 41 static final String CONTEXTUAL_SEARCH_TAP_RESOLVE_LIMIT_FOR_DECIDED = |
| 42 "tap_resolve_limit_for_decided"; |
| 43 static final String CONTEXTUAL_SEARCH_TAP_PREFETCH_LIMIT_FOR_DECIDED = |
| 44 "tap_prefetch_limit_for_decided"; |
| 45 static final String CONTEXTUAL_SEARCH_TAP_RESOLVE_LIMIT_FOR_UNDECIDED = |
| 46 "tap_resolve_limit_for_undecided"; |
| 47 static final String CONTEXTUAL_SEARCH_TAP_PREFETCH_LIMIT_FOR_UNDECIDED = |
| 48 "tap_prefetch_limit_for_undecided"; |
| 49 |
| 50 private static final String[] CJK_LANGUAGE_CODES = {"zh", "ja", "ko"}; |
| 51 private static final String ENGLISH_LANGUAGE_CODE = "en"; |
| 52 |
| 53 // The default navigation-detection-delay in milliseconds. |
| 54 private static final int DEFAULT_TAP_NAVIGATION_DETECTION_DELAY = 16; |
| 55 |
| 56 static final int UNLIMITED_TAPS = -1; |
| 57 private static final int DEFAULT_TAP_RESOLVE_LIMIT_FOR_DECIDED = UNLIMITED_T
APS; |
| 58 private static final int DEFAULT_TAP_PREFETCH_LIMIT_FOR_DECIDED = UNLIMITED_
TAPS; |
| 59 private static final int DEFAULT_TAP_RESOLVE_LIMIT_FOR_UNDECIDED = 100; |
| 60 private static final int DEFAULT_TAP_PREFETCH_LIMIT_FOR_UNDECIDED = 10; |
| 61 |
| 62 // Cached value to avoid repeated and redundant JNI operations. |
| 63 private static Boolean sEnabled; |
| 64 |
| 65 /** |
| 66 * Don't instantiate. |
| 67 */ |
| 68 private ContextualSearchFieldTrial() {} |
| 69 |
| 70 /** |
| 71 * Checks the current Variations parameters associated with the active group
as well as the |
| 72 * Chrome preference to determine if the service is enabled. |
| 73 * @return Whether Contextual Search is enabled or not. |
| 74 */ |
| 75 public static boolean isEnabled(Context context) { |
| 76 if (sEnabled == null) { |
| 77 sEnabled = detectEnabled(context); |
| 78 } |
| 79 return sEnabled.booleanValue(); |
| 80 } |
| 81 |
| 82 private static boolean detectEnabled(Context context) { |
| 83 if (DeviceFormFactor.isTablet(context) || SysUtils.isLowEndDevice()) { |
| 84 return false; |
| 85 } |
| 86 |
| 87 // This is used for instrumentation tests (i.e. it is not a user-flippab
le flag). We cannot |
| 88 // use Variations params because in the test harness, the initialization
comes before any |
| 89 // native methods are available. And the ContextualSearchManager is init
ialized very early |
| 90 // in the Chrome initialization. |
| 91 if (CommandLine.getInstance().hasSwitch( |
| 92 ChromeSwitches.ENABLE_CONTEXTUAL_SEARCH_FOR_TESTING)) { |
| 93 return true; |
| 94 } |
| 95 |
| 96 // Allow this user-flippable flag to disable the feature. |
| 97 if (CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_CONTEXTUA
L_SEARCH)) { |
| 98 return false; |
| 99 } |
| 100 |
| 101 // Allow this user-flippable flag to override disabling due to language. |
| 102 if (CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_CONTEXTUAL
_SEARCH)) { |
| 103 return true; |
| 104 } |
| 105 |
| 106 String languageCode = Locale.getDefault().getLanguage(); |
| 107 if (getBooleanParam(CONTEXTUAL_SEARCH_DISABLE_FOR_NON_ENGLISH) |
| 108 && !languageCode.equals(ENGLISH_LANGUAGE_CODE)) { |
| 109 return false; |
| 110 } |
| 111 |
| 112 if (getBooleanParam(CONTEXTUAL_SEARCH_DISABLE_FOR_CJK) |
| 113 && Arrays.asList(CJK_LANGUAGE_CODES).contains(languageCode)) { |
| 114 return false; |
| 115 } |
| 116 |
| 117 if (ChromeVersionInfo.isLocalBuild()) return true; |
| 118 |
| 119 return getBooleanParam(CONTEXTUAL_SEARCH_ENABLED_PARAM); |
| 120 } |
| 121 |
| 122 /** |
| 123 * @return Whether the promo is configured for Opt-out. |
| 124 */ |
| 125 static boolean isPromoOptOut() { |
| 126 return true; |
| 127 } |
| 128 |
| 129 /** |
| 130 * Gets whether the promo should be triggered on longpress only. |
| 131 * @return {@code true} iff Finch says we should trigger the promo only on t
ouch-and-hold. |
| 132 */ |
| 133 static boolean isPromoLongpressTriggeredOnly() { |
| 134 return getBooleanParam(CONTEXTUAL_SEARCH_PROMO_ON_LONGPRESS_ONLY); |
| 135 } |
| 136 |
| 137 /** |
| 138 * @return Whether the promo should be triggered by a limited number of taps
. |
| 139 */ |
| 140 public static boolean isPromoLimitedByTapCounts() { |
| 141 return getBooleanParam(CONTEXTUAL_SEARCH_PROMO_ON_LIMITED_TAPS); |
| 142 } |
| 143 |
| 144 /** |
| 145 * @return The maximum number of times the promo can be triggered by a tap,
or |
| 146 * {@code ContextualSearchUma#PROMO_TAPS_REMAINING_INVALID} if no value is p
resent in the finch |
| 147 * configuration. |
| 148 */ |
| 149 static int getPromoTapTriggeredLimit() { |
| 150 return getIntParamValueOrDefault(CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_L
IMIT, |
| 151 UNLIMITED_TAPS); |
| 152 } |
| 153 |
| 154 /** |
| 155 * @return The delay to use for navigation-detection when triggering on a Ta
p. |
| 156 */ |
| 157 static int getNavigationDetectionDelay() { |
| 158 return getIntParamValueOrDefault(CONTEXTUAL_SEARCH_NAVIGATION_DETECTION_
DELAY, |
| 159 DEFAULT_TAP_NAVIGATION_DETECTION_DELAY); |
| 160 } |
| 161 |
| 162 /** |
| 163 * @return The limit on the number of taps to resolve for decided users, or
the default if no |
| 164 * value is present in the Finch configuration. |
| 165 */ |
| 166 static int getTapResolveLimitForDecided() { |
| 167 return getIntParamValueOrDefault(CONTEXTUAL_SEARCH_TAP_RESOLVE_LIMIT_FOR
_DECIDED, |
| 168 DEFAULT_TAP_RESOLVE_LIMIT_FOR_DECIDED); |
| 169 } |
| 170 |
| 171 /** |
| 172 * @return The limit on the number of prefetches to issue for decided users,
or the default |
| 173 * if no value is present. |
| 174 */ |
| 175 static int getTapPrefetchLimitForDecided() { |
| 176 return getIntParamValueOrDefault(CONTEXTUAL_SEARCH_TAP_PREFETCH_LIMIT_FO
R_DECIDED, |
| 177 DEFAULT_TAP_PREFETCH_LIMIT_FOR_DECIDED); |
| 178 } |
| 179 |
| 180 /** |
| 181 * @return The limit on the number of taps to resolve for undecided users, o
r the default if no |
| 182 * value is present in the Finch configuration. |
| 183 */ |
| 184 static int getTapResolveLimitForUndecided() { |
| 185 return getIntParamValueOrDefault(CONTEXTUAL_SEARCH_TAP_RESOLVE_LIMIT_FOR
_UNDECIDED, |
| 186 DEFAULT_TAP_RESOLVE_LIMIT_FOR_UNDECIDED); |
| 187 } |
| 188 |
| 189 /** |
| 190 * @return The limit on the number of prefetches to issue for undecided user
s, or the default |
| 191 * if no value is present. |
| 192 */ |
| 193 static int getTapPrefetchLimitForUndecided() { |
| 194 return getIntParamValueOrDefault(CONTEXTUAL_SEARCH_TAP_PREFETCH_LIMIT_FO
R_UNDECIDED, |
| 195 DEFAULT_TAP_PREFETCH_LIMIT_FOR_UNDECIDED); |
| 196 } |
| 197 |
| 198 // -------------------------------------------------------------------------
------------------- |
| 199 // Helpers. |
| 200 // -------------------------------------------------------------------------
------------------- |
| 201 |
| 202 /** |
| 203 * Gets a boolean Finch parameter, assuming the <paramName>="true" format.
Also checks for a |
| 204 * command-line switch with the same name, for easy local testing. |
| 205 * @param paramName The name of the Finch parameter (or command-line switch)
to get a value for. |
| 206 * @return Whether the Finch param is defined with a value "true", if there'
s a command-line |
| 207 * flag present with any value. |
| 208 */ |
| 209 private static boolean getBooleanParam(String paramName) { |
| 210 if (CommandLine.getInstance().hasSwitch(paramName)) { |
| 211 return true; |
| 212 } |
| 213 return TextUtils.equals(CONTEXTUAL_SEARCH_ENABLED_VALUE, |
| 214 VariationsAssociatedData.getVariationParamValue(CONTEXTUAL_SEARC
H_FIELD_TRIAL_NAME, |
| 215 paramName)); |
| 216 } |
| 217 |
| 218 /** |
| 219 * Returns an integer value for a Finch parameter, or the default value if n
o parameter exists |
| 220 * in the current configuration. Also checks for a command-line switch with
the same name. |
| 221 * @param paramName The name of the Finch parameter (or command-line switch)
to get a value for. |
| 222 * @param defaultValue The default value to return when there's no param or
switch. |
| 223 * @return An integer value -- either the param or the default. |
| 224 */ |
| 225 private static int getIntParamValueOrDefault(String paramName, int defaultVa
lue) { |
| 226 String value = CommandLine.getInstance().getSwitchValue(paramName); |
| 227 if (TextUtils.isEmpty(value)) { |
| 228 value = VariationsAssociatedData.getVariationParamValue( |
| 229 CONTEXTUAL_SEARCH_FIELD_TRIAL_NAME, paramName); |
| 230 } |
| 231 if (!TextUtils.isEmpty(value)) { |
| 232 try { |
| 233 return Integer.parseInt(value); |
| 234 } catch (NumberFormatException e) { |
| 235 return defaultValue; |
| 236 } |
| 237 } |
| 238 |
| 239 return defaultValue; |
| 240 } |
| 241 } |
OLD | NEW |