Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
9 import org.chromium.base.VisibleForTesting;
10 import org.chromium.chrome.browser.ChromeVersionInfo;
11 import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionCon troller.SelectionType;
12 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
13 import org.chromium.chrome.browser.preferences.NetworkPredictionOptions;
14 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
15
16 import java.net.URL;
17
18 import javax.annotation.Nullable;
19
20
21 /**
22 * Handles policy decisions for the {@code ContextualSearchManager}.
23 */
24 class ContextualSearchPolicy {
25 private static final int PROMO_TAPS_NOT_LIMITED = -1;
26 private static final int PROMO_TAPS_DISABLED_BIAS = -2;
27
28 private static ContextualSearchPolicy sInstance;
29
30 private final ChromePreferenceManager mPreferenceManager;
31
32 // Members used only for testing purposes.
33 private boolean mDidOverrideDecidedStateForTesting;
34 private boolean mDecidedStateForTesting;
35 private boolean mDidResetTapCounters;
36
37 static ContextualSearchPolicy getInstance(Context context) {
38 if (sInstance == null) {
39 sInstance = new ContextualSearchPolicy(context);
40 }
41 return sInstance;
42 }
43
44 /**
45 * @param context The Android Context.
46 */
47 ContextualSearchPolicy(Context context) {
48 mPreferenceManager = ChromePreferenceManager.getInstance(context);
49 }
50
51 // TODO(donnd): Consider adding a test-only constructor that uses dependency injection of a
52 // preference manager and PrefServiceBridge. Currently this is not possible because the
53 // PrefServiceBridge is final.
54
55 /**
56 * @return The number of additional times to show the promo on tap, 0 if it should not be shown,
57 * or a negative value if the counter has been disabled.
58 */
59 int getPromoTapsRemaining() {
60 if (ContextualSearchFieldTrial.isPromoLimitedByTapCounts()) {
61 int count = mPreferenceManager.getContextualSearchTapTriggeredPromoC ount();
62
63 // Return a negative value if opt-out promo counter has been disable d.
64 if (isOptOutPromoAvailable() && !isOptOutPromoCounterEnabled(count)) return count;
65
66 int limit = ContextualSearchFieldTrial.getPromoTapTriggeredLimit();
67 if (limit >= 0) return Math.max(0, limit - count);
68 }
69
70 return PROMO_TAPS_NOT_LIMITED;
71 }
72
73 /**
74 * @return Whether a Tap gesture is currently supported as a trigger for the feature.
75 */
76 boolean isTapSupported() {
77 if (!isUserUndecided()) return true;
78
79 if (ContextualSearchFieldTrial.isPromoLongpressTriggeredOnly()) return f alse;
80
81 return getPromoTapsRemaining() != 0;
82 }
83
84 /**
85 * @return whether or not the Contextual Search Result should be preloaded b efore the user
86 * explicitly interacts with the feature.
87 */
88 boolean shouldPrefetchSearchResult(boolean isTapTriggered) {
89 if (PrefServiceBridge.getInstance().getNetworkPredictionOptions()
90 == NetworkPredictionOptions.NETWORK_PREDICTION_NEVER) {
91 return false;
92 }
93
94 if (isTapPrefetchBeyondTheLimit()) return false;
95
96 // If we're not resolving the tap due to the tap limit, we should not pr eload either.
97 if (isTapResolveBeyondTheLimit()) return false;
98
99 // We never preload on long-press so users can cut & paste without hitti ng the servers.
100 return isTapTriggered;
101 }
102
103 /**
104 * Returns whether the previous tap (the tap last counted) should resolve.
105 * @return Whether the previous tap should resolve.
106 */
107 boolean shouldPreviousTapResolve(@Nullable URL url) {
108 if (isTapResolveBeyondTheLimit()) {
109 return false;
110 }
111
112 if (isOptOutPromoAvailable()) {
113 return isBasePageHTTP(url);
114 }
115
116 return true;
117 }
118
119 /**
120 * Returns whether surrounding context can be accessed by other systems or n ot.
121 * @baseContentViewUrl The URL of the base page.
122 * @return Whether surroundings are available.
123 */
124 boolean canSendSurroundings(@Nullable URL baseContentViewUrl) {
125 if (isUserUndecided()) return false;
126
127 if (isOptOutPromoAvailable()) {
128 return isBasePageHTTP(baseContentViewUrl);
129 }
130
131 return true;
132 }
133
134 /**
135 * @return Whether the Opt-out promo is available to be shown in any panel.
136 */
137 boolean isOptOutPromoAvailable() {
138 return ContextualSearchFieldTrial.isPromoOptOut() && isUserUndecided();
139 }
140
141 /**
142 * @return Whether the classic opt-in promo is available.
143 */
144 protected boolean isOptInPromoAvailable() {
145 return false;
146 }
147
148 /**
149 * Registers that a tap has taken place by incrementing tap-tracking counter s.
150 */
151 void registerTap() {
152 if (isOptInPromoAvailable() || isOptOutPromoAvailable()) {
153 int count = mPreferenceManager.getContextualSearchTapTriggeredPromoC ount();
154 // Bump the counter only when it is still enabled.
155 if (isOptInPromoAvailable() || isOptOutPromoCounterEnabled(count)) {
156 mPreferenceManager.setContextualSearchTapTriggeredPromoCount(++c ount);
157 }
158 }
159 if (isTapLimited()) {
160 int count = mPreferenceManager.getContextualSearchTapCount();
161 mPreferenceManager.setContextualSearchTapCount(++count);
162 }
163 }
164
165 /**
166 * Resets all the "tap" counters.
167 */
168 void resetTapCounters() {
169 // Always completely reset the tap counters, since tests push beyond lim its: this
170 // would affect subsequent tests unless they can reset without having a limit.
171 mPreferenceManager.setContextualSearchTapCount(0);
172
173 // Disable the "promo tap" counter, but only if we're using the Opt-out onboarding.
174 // For Opt-in, we never disable the promo tap counter.
175 if (isOptOutPromoAvailable()) disableOptOutPromoCounter();
176 mDidResetTapCounters = true;
177 }
178
179 @VisibleForTesting
180 void overrideDecidedStateForTesting(boolean decidedState) {
181 mDidOverrideDecidedStateForTesting = true;
182 mDecidedStateForTesting = decidedState;
183 }
184
185 @VisibleForTesting
186 boolean didResetTapCounters() {
187 return mDidResetTapCounters;
188 }
189
190 /**
191 * @return Whether a verbatim request should be made for the given base page , assuming there
192 * is no exiting request.
193 */
194 boolean shouldCreateVerbatimRequest(ContextualSearchSelectionController cont roller,
195 @Nullable URL basePageUrl) {
196 // TODO(donnd): refactor to make the controller a member of this class?
197 return (controller.getSelectedText() != null
198 && (controller.getSelectionType() == SelectionType.LONG_PRESS
199 || (controller.getSelectionType() == SelectionType.TAP
200 && !shouldPreviousTapResolve(basePageUrl))));
201 }
202
203 /**
204 * Determines whether an error from a search term resolution request should
205 * be shown to the user, or not.
206 */
207 boolean shouldShowErrorCodeInBar() {
208 // Builds with lots of real users should not see raw error codes.
209 return !(ChromeVersionInfo.isStableBuild() || ChromeVersionInfo.isBetaBu ild());
210 }
211
212 // ------------------------------------------------------------------------- -------------------
213 // Opt-out style Promo counter
214 //
215 // The Opt-out style promo tap counter needs to do two things:
216 // 1) Count Taps that trigger the promo, so they can be limited.
217 // 2) Support a "disabled" state; when the user opens the panel then Taps tr igger from then on.
218 // We use a single persistent setting to record both meanings by using a neg ative value to
219 // indicate disabled.
220 //
221 // TODO(donnd): make a separate class for this kind of counter.
222 // ------------------------------------------------------------------------- -------------------
223
224 /**
225 * Determines if the given Opt-out style promo counter represents a count of promo taps in
226 * the enabled state.
227 * @param counter The persistent counter value to consider.
228 * @return Whether the given counter is enabled.
229 */
230 private boolean isOptOutPromoCounterEnabled(int counter) {
231 return counter >= 0;
232 }
233
234 /**
235 * Generates an equivalent counter value with the enabled state opposite of the given value.
236 * @param count The current value of the counter.
237 * @return The equivalent value in with its enabled/disabled state toggled.
238 */
239 private int toggleOptOutPromoCounterEnabled(int count) {
240 return PROMO_TAPS_DISABLED_BIAS - count;
241 }
242
243 /**
244 * Disables the Opt-out promo counter, unless it is already disabled.
245 */
246 private void disableOptOutPromoCounter() {
247 int count = mPreferenceManager.getContextualSearchTapTriggeredPromoCount ();
248 if (isOptOutPromoCounterEnabled(count)) {
249 count = toggleOptOutPromoCounterEnabled(count);
250 mPreferenceManager.setContextualSearchTapTriggeredPromoCount(count);
251 }
252 }
253
254 // ------------------------------------------------------------------------- -------------------
255 // Private helpers.
256 // ------------------------------------------------------------------------- -------------------
257
258 /**
259 * @return Whether a promo is needed because the user is still undecided
260 * on enabling or disabling the feature.
261 */
262 private boolean isUserUndecided() {
263 // TODO(donnd) use dependency injection for the PrefServiceBridge instea d!
264 if (mDidOverrideDecidedStateForTesting) return !mDecidedStateForTesting;
265
266 return PrefServiceBridge.getInstance().isContextualSearchUninitialized() ;
267 }
268
269 /**
270 * @param url The URL of the base page.
271 * @return Whether the given content view is for an HTTP page.
272 */
273 private boolean isBasePageHTTP(@Nullable URL url) {
274 // We shouldn't be checking HTTP unless we're in the opt-out promo which
275 // treats HTTP differently.
276 assert ContextualSearchFieldTrial.isPromoOptOut();
277 return url != null && "http".equals(url.getProtocol());
278 }
279
280 /**
281 * @return Whether the tap resolve limit has been exceeded.
282 */
283 private boolean isTapResolveBeyondTheLimit() {
284 return isTapResolveLimited()
285 && mPreferenceManager.getContextualSearchTapCount() > getTapReso lveLimit();
286 }
287
288 /**
289 * @return Whether the tap resolve limit has been exceeded.
290 */
291 private boolean isTapPrefetchBeyondTheLimit() {
292 return isTapPrefetchLimited()
293 && mPreferenceManager.getContextualSearchTapCount() > getTapPref etchLimit();
294 }
295
296 /**
297 * Whether taps for decided users are limited, either for prefetch or resolv e.
298 */
299 private boolean isTapLimited() {
300 return isTapPrefetchLimited() || isTapResolveLimited();
301 }
302
303 /**
304 * @return Whether a tap gesture is resolve-limited.
305 */
306 private boolean isTapResolveLimited() {
307 return isUserUndecided()
308 ? isTapResolveLimitedForUndecided()
309 : isTapResolveLimitedForDecided();
310 }
311
312 /**
313 * @return Whether a tap gesture is resolve-limited.
314 */
315 private boolean isTapPrefetchLimited() {
316 return isUserUndecided()
317 ? isTapPrefetchLimitedForUndecided()
318 : isTapPrefetchLimitedForDecided();
319 }
320
321 /**
322 * @return The limit of the number of taps to prefetch.
323 */
324 private int getTapPrefetchLimit() {
325 return isUserUndecided()
326 ? ContextualSearchFieldTrial.getTapPrefetchLimitForUndecided()
327 : ContextualSearchFieldTrial.getTapPrefetchLimitForDecided();
328 }
329
330 /**
331 * @return The limit of the number of taps to resolve using search term reso lution.
332 */
333 private int getTapResolveLimit() {
334 return isUserUndecided()
335 ? ContextualSearchFieldTrial.getTapResolveLimitForUndecided()
336 : ContextualSearchFieldTrial.getTapResolveLimitForDecided();
337 }
338
339 /**
340 * @return Whether Search Term Resolution in response to a Tap gesture is li mited for decided
341 * users.
342 */
343 private boolean isTapResolveLimitedForDecided() {
344 return ContextualSearchFieldTrial.getTapResolveLimitForDecided()
345 != ContextualSearchFieldTrial.UNLIMITED_TAPS;
346 }
347
348 /**
349 * @return Whether prefetch in response to a Tap gesture is limited for deci ded users.
350 */
351 private boolean isTapPrefetchLimitedForDecided() {
352 return ContextualSearchFieldTrial.getTapPrefetchLimitForDecided()
353 != ContextualSearchFieldTrial.UNLIMITED_TAPS;
354 }
355
356 /**
357 * @return Whether Search Term Resolution in response to a Tap gesture is li mited for undecided
358 * users.
359 */
360 private boolean isTapResolveLimitedForUndecided() {
361 return ContextualSearchFieldTrial.getTapResolveLimitForUndecided()
362 != ContextualSearchFieldTrial.UNLIMITED_TAPS;
363 }
364
365 /**
366 * @return Whether prefetch in response to a Tap gesture is limited for unde cided users.
367 */
368 private boolean isTapPrefetchLimitedForUndecided() {
369 return ContextualSearchFieldTrial.getTapPrefetchLimitForUndecided()
370 != ContextualSearchFieldTrial.UNLIMITED_TAPS;
371 }
372 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698