1 // Copyright 2014 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.
5 #ifndef COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_FIELD_TRIAL_H_
6 #define COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_FIELD_TRIAL_H_
12 #include "base/basictypes.h"
13 #include "base/gtest_prod_util.h"
14 #include "components/metrics/proto/omnibox_event.pb.h"
15 #include "components/omnibox/browser/autocomplete_match_type.h"
21 // The set of parameters customizing the HUP scoring.
22 struct HUPScoringParams
{
23 // A set of parameters describing how to cap a given count score. First,
24 // we apply a half-life based decay of the given count and then find the
25 // maximum relevance score based on the decay factor or counts specified
26 // in the corresponding bucket list. See comment on |buckets_| for details.
29 // Stores the max relevance at each count/decay factor threshold.
30 typedef std::pair
<double, int> CountMaxRelevance
;
35 // Computes a half-life time decay given the |elapsed_time|.
36 double HalfLifeTimeDecay(const base::TimeDelta
& elapsed_time
) const;
38 int relevance_cap() const { return relevance_cap_
; }
39 void set_relevance_cap(int relevance_cap
) {
40 relevance_cap_
= relevance_cap
;
43 int half_life_days() const { return half_life_days_
; }
44 void set_half_life_days(int half_life_days
) {
45 half_life_days_
= half_life_days
;
48 bool use_decay_factor() const { return use_decay_factor_
; }
49 void set_use_decay_factor(bool use_decay_factor
) {
50 use_decay_factor_
= use_decay_factor
;
53 std::vector
<CountMaxRelevance
>& buckets() { return buckets_
; }
54 const std::vector
<CountMaxRelevance
>& buckets() const { return buckets_
; }
57 // History matches with relevance score greater or equal to |relevance_cap_|
58 // are not affected by this experiment.
59 // Set to -1, if there is no relevance cap in place and all matches are
60 // subject to demotion.
63 // Half life time for a decayed count as measured since the last visit.
64 // Set to -1 if not used.
67 // The relevance score caps at successively decreasing threshold values.
68 // The thresholds are either decayed counts or decay factors, depending on
69 // the value of |use_decay_factor_|.
71 // Consider this example specifying the decayed counts:
72 // [(1, 1000), (0.5, 500), (0, 100)]
73 // If decayed count is 2 (which is >= 1), the corresponding match's maximum
74 // relevance will be capped at 1000. In case of 0.5, the score is capped
75 // at 500. Anything below 0.5 is capped at 100.
77 // This list is sorted by the pair's first element in descending order.
78 std::vector
<CountMaxRelevance
> buckets_
;
80 // True when the bucket thresholds are decay factors rather than counts.
81 bool use_decay_factor_
;
84 HUPScoringParams() : experimental_scoring_enabled(false) {}
86 bool experimental_scoring_enabled
;
88 ScoreBuckets typed_count_buckets
;
90 // Used only when the typed count is 0.
91 ScoreBuckets visited_count_buckets
;
94 // This class manages the Omnibox field trials.
95 class OmniboxFieldTrial
{
97 // A mapping that contains multipliers indicating that matches of the
98 // specified type should have their relevance score multiplied by the
99 // given number. Omitted types are assumed to have multipliers of 1.0.
100 typedef std::map
<AutocompleteMatchType::Type
, float> DemotionMultipliers
;
102 // Activates all dynamic field trials. The main difference between
103 // the autocomplete dynamic and static field trials is that the former
104 // don't require any code changes on the Chrome side as they are controlled
105 // on the server side. Chrome binary simply propagates all necessary
106 // information through the X-Client-Data header.
107 // This method may be called multiple times.
108 static void ActivateDynamicTrials();
110 // ---------------------------------------------------------
111 // For any experiment that's part of the bundled omnibox field trial.
113 // Returns a bitmap containing AutocompleteProvider::Type values
114 // that should be disabled in AutocompleteController.
115 static int GetDisabledProviderTypes();
117 // Returns whether the user is in any dynamic field trial where the
118 // group has a the prefix |group_prefix|.
119 static bool HasDynamicFieldTrialGroupPrefix(const char *group_prefix
);
121 // ---------------------------------------------------------
122 // For the suggest field trial.
124 // Populates |field_trial_hash| with hashes of the active suggest field trial
126 static void GetActiveSuggestFieldTrialHashes(
127 std::vector
<uint32
>* field_trial_hash
);
129 // ---------------------------------------------------------
130 // For the AutocompleteController "stop timer" field trial.
132 // Returns the duration to be used for the AutocompleteController's stop
133 // timer. Returns the default value of 1.5 seconds if the stop timer
134 // override experiment isn't active or if parsing the experiment-provided
136 static base::TimeDelta
StopTimerFieldTrialDuration();
138 // ---------------------------------------------------------
139 // For the ZeroSuggestProvider field trial.
141 // Returns whether the user is in any field trial where the
142 // ZeroSuggestProvider should be used to get suggestions when the
143 // user clicks on the omnibox but has not typed anything yet.
144 static bool InZeroSuggestFieldTrial();
146 // Returns whether the user is in a ZeroSuggest field trial, which shows
147 // most visited URLs. This is true for both "MostVisited" and
148 // "MostVisitedWithoutSERP" trials.
149 static bool InZeroSuggestMostVisitedFieldTrial();
151 // Returns whether the user is in ZeroSuggest field trial showing most
152 // visited URLs except it doesn't show suggestions on Google search result
154 static bool InZeroSuggestMostVisitedWithoutSerpFieldTrial();
156 // Returns whether the user is in a ZeroSuggest field trial and URL-based
157 // suggestions can continue to appear after the user has started typing.
158 static bool InZeroSuggestAfterTypingFieldTrial();
160 // Returns whether the user is in a ZeroSuggest field trial, but should
161 // show recently searched-for queries instead.
162 static bool InZeroSuggestPersonalizedFieldTrial();
164 // ---------------------------------------------------------
165 // For the ShortcutsScoringMaxRelevance experiment that's part of the
166 // bundled omnibox field trial.
168 // If the user is in an experiment group that, given the provided
169 // |current_page_classification| context, changes the maximum relevance
170 // ShortcutsProvider::CalculateScore() is supposed to assign, extract
171 // that maximum relevance score and put in in |max_relevance|. Returns
172 // true on a successful extraction. CalculateScore()'s return value is
173 // a product of this maximum relevance score and some attenuating factors
174 // that are all between 0 and 1. (Note that Shortcuts results may have
175 // their scores reduced later if the assigned score is higher than allowed
176 // for non-inlineable results. Shortcuts results are not allowed to be
178 static bool ShortcutsScoringMaxRelevance(
179 metrics::OmniboxEventProto::PageClassification
180 current_page_classification
,
183 // ---------------------------------------------------------
184 // For the SearchHistory experiment that's part of the bundled omnibox
187 // Returns true if the user is in the experiment group that, given the
188 // provided |current_page_classification| context, scores search history
189 // query suggestions less aggressively so that they don't inline.
190 static bool SearchHistoryPreventInlining(
191 metrics::OmniboxEventProto::PageClassification
192 current_page_classification
);
194 // Returns true if the user is in the experiment group that, given the
195 // provided |current_page_classification| context, disables all query
196 // suggestions from search history.
197 static bool SearchHistoryDisable(
198 metrics::OmniboxEventProto::PageClassification
199 current_page_classification
);
201 // ---------------------------------------------------------
202 // For the DemoteByType experiment that's part of the bundled omnibox field
205 // If the user is in an experiment group that, in the provided
206 // |current_page_classification| context, demotes the relevance scores
207 // of certain types of matches, populates the |demotions_by_type| map
208 // appropriately. Otherwise, sets |demotions_by_type| to its default
209 // value based on the context.
210 static void GetDemotionsByType(
211 metrics::OmniboxEventProto::PageClassification
212 current_page_classification
,
213 DemotionMultipliers
* demotions_by_type
);
215 // ---------------------------------------------------------
216 // For the HistoryURL provider new scoring experiment that is part of the
217 // bundled omnibox field trial.
219 // Initializes the HUP |scoring_params| based on the active HUP scoring
220 // experiment. If there is no such experiment, this function simply sets
221 // |scoring_params|->experimental_scoring_enabled to false.
222 static void GetDefaultHUPScoringParams(HUPScoringParams
* scoring_params
);
223 static void GetExperimentalHUPScoringParams(HUPScoringParams
* scoring_params
);
225 // For the HQPBookmarkValue experiment that's part of the
226 // bundled omnibox field trial.
228 // Returns the value an untyped visit to a bookmark should receive.
229 // Compare this value with the default of 1 for non-bookmarked untyped
230 // visits to pages and the default of 20 for typed visits. Returns
231 // 10 if the bookmark value experiment isn't active.
232 static int HQPBookmarkValue();
234 // ---------------------------------------------------------
235 // For the HQPAllowMatchInTLD experiment that's part of the
236 // bundled omnibox field trial.
238 // Returns true if HQP should allow an input term to match in the
239 // top level domain (e.g., .com) of a URL. Returns false if the
240 // allow match in TLD experiment isn't active.
241 static bool HQPAllowMatchInTLDValue();
243 // ---------------------------------------------------------
244 // For the HQPAllowMatchInScheme experiment that's part of the
245 // bundled omnibox field trial.
247 // Returns true if HQP should allow an input term to match in the
248 // scheme (e.g., http://) of a URL. Returns false if the allow
249 // match in scheme experiment isn't active.
250 static bool HQPAllowMatchInSchemeValue();
252 // ---------------------------------------------------------
253 // For SearchProvider related experiments.
255 // Returns true if the search provider should not be caching results.
256 static bool DisableResultsCaching();
258 // Returns how the search provider should poll Suggest. Currently, we support
259 // measuring polling delay from the last keystroke or last suggest request.
260 static void GetSuggestPollingStrategy(bool* from_last_keystroke
,
261 int* polling_delay_ms
);
263 // ---------------------------------------------------------
264 // For HQP scoring related experiments to control the topicality and scoring
265 // ranges of relevancy scores.
267 // Returns true if HQP experimental scoring is enabled. Returns false if
268 // |kHQPExperimentalScoringEnabledParam| is not specified in the field trial.
269 static bool HQPExperimentalScoringEnabled();
271 // Returns the scoring buckets for HQP experiments. Returns empty string
272 // in case |kHQPExperimentalScoringBucketsParam| or
273 // |kHQPExperimentalScoringEnabledParam| is not specified in the
274 // field trial. Scoring buckets are stored in string form giving mapping from
275 // (topicality_score, frequency_score) to final relevance score.
276 // Please see GetRelevancyScore() under
277 // chrome/browser/history::ScoredHistoryMatch for details.
278 static std::string
HQPExperimentalScoringBuckets();
280 // Returns the topicality threshold for HQP experiments. Returns -1 if
281 // |kHQPExperimentalScoringTopicalityThresholdParam| or
282 // |kHQPExperimentalScoringEnabledParam| is not specified in the field trial.
283 static float HQPExperimentalTopicalityThreshold();
285 // ---------------------------------------------------------
286 // For the HQPFixFrequencyScoring experiment that's part of the
287 // bundled omnibox field trial.
289 // Returns true if HQP should apply the bug fixes to the GetFrequency()
291 static bool HQPFixFrequencyScoringBugs();
293 // ---------------------------------------------------------
294 // For the HQPNumTitleWords experiment that's part of the
295 // bundled omnibox field trial.
297 // Returns the number of title words that are allowed to contribute
298 // to the topicality score. Words later in the title are ignored.
299 // Returns 10 as a default if the experiment isn't active.
300 static size_t HQPNumTitleWordsToAllow();
302 // ---------------------------------------------------------
303 // For the HQPAlsoDoHUPLikeScoring experiment that's part of the
304 // bundled omnibox field trial.
306 // Returns whether HistoryQuick provider (HQP) should attempt to score
307 // suggestions also with a HistoryURL-provider-like (HUP-like) mode, and
308 // assign suggestions the max of this score and the normal score.
309 // Returns false if the experiment isn't active.
310 static bool HQPAlsoDoHUPLikeScoring();
312 // ---------------------------------------------------------
313 // For the PreventUWYTDefaultForNonURLInputs experiment that's part of the
314 // bundled omnibox field trial.
316 // Returns true if HistoryURL provider should prohibit the URL-what-you-
317 // typed match from being the legal default match for non-URL inputs.
318 // If this behavior is active, some code in AutocompleteInput::Parse() also
319 // gets disabled; this code is unnecessary given the not-allowed-to-be-
320 // default constraint. Returns false if the experiment isn't active.
321 static bool PreventUWYTDefaultForNonURLInputs();
323 // ---------------------------------------------------------
324 // Exposed publicly for the sake of unittests.
325 static const char kBundledExperimentFieldTrialName
[];
326 // Rule names used by the bundled experiment.
327 static const char kDisableProvidersRule
[];
328 static const char kShortcutsScoringMaxRelevanceRule
[];
329 static const char kSearchHistoryRule
[];
330 static const char kDemoteByTypeRule
[];
331 static const char kHQPBookmarkValueRule
[];
332 static const char kHQPDiscountFrecencyWhenFewVisitsRule
[];
333 static const char kHQPAllowMatchInTLDRule
[];
334 static const char kHQPAllowMatchInSchemeRule
[];
335 static const char kZeroSuggestRule
[];
336 static const char kZeroSuggestVariantRule
[];
337 static const char kSuggestVariantRule
[];
338 static const char kDisableResultsCachingRule
[];
339 static const char kMeasureSuggestPollingDelayFromLastKeystrokeRule
[];
340 static const char kSuggestPollingDelayMsRule
[];
341 static const char kHQPFixFrequencyScoringBugsRule
[];
342 static const char kHQPNumTitleWordsRule
[];
343 static const char kHQPAlsoDoHUPLikeScoringRule
[];
344 static const char kPreventUWYTDefaultForNonURLInputsRule
[];
346 // Parameter names used by the HUP new scoring experiments.
347 static const char kHUPNewScoringEnabledParam
[];
348 static const char kHUPNewScoringTypedCountRelevanceCapParam
[];
349 static const char kHUPNewScoringTypedCountHalfLifeTimeParam
[];
350 static const char kHUPNewScoringTypedCountScoreBucketsParam
[];
351 static const char kHUPNewScoringTypedCountUseDecayFactorParam
[];
352 static const char kHUPNewScoringVisitedCountRelevanceCapParam
[];
353 static const char kHUPNewScoringVisitedCountHalfLifeTimeParam
[];
354 static const char kHUPNewScoringVisitedCountScoreBucketsParam
[];
355 static const char kHUPNewScoringVisitedCountUseDecayFactorParam
[];
357 // Parameter names used by the HQP experimental scoring experiments.
358 static const char kHQPExperimentalScoringEnabledParam
[];
359 static const char kHQPExperimentalScoringBucketsParam
[];
360 static const char kHQPExperimentalScoringTopicalityThresholdParam
[];
362 // The amount of time to wait before sending a new suggest request after the
363 // previous one unless overridden by a field trial parameter.
364 // Non-const because some unittests modify this value.
365 static int kDefaultMinimumTimeBetweenSuggestQueriesMs
;
368 friend class OmniboxFieldTrialTest
;
370 // The bundled omnibox experiment comes with a set of parameters
371 // (key-value pairs). Each key indicates a certain rule that applies in
372 // a certain context. The value indicates what the consequences of
373 // applying the rule are. For example, the value of a SearchHistory rule
374 // in the context of a search results page might indicate that we should
375 // prevent search history matches from inlining.
377 // This function returns the value associated with the |rule| that applies
378 // in the current context (which currently consists of |page_classification|
379 // and whether Instant Extended is enabled). If no such rule exists in the
380 // current context, fall back to the rule in various wildcard contexts and
381 // return its value if found. If the rule remains unfound in the global
382 // context, returns the empty string. For more details, including how we
383 // prioritize different wildcard contexts, see the implementation. How to
384 // interpret the value is left to the caller; this is rule-dependent.
385 static std::string
GetValueForRuleInContext(
386 const std::string
& rule
,
387 metrics::OmniboxEventProto::PageClassification page_classification
);
389 DISALLOW_IMPLICIT_CONSTRUCTORS(OmniboxFieldTrial
);
392 #endif // COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_FIELD_TRIAL_H_