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_OMNIBOX_FIELD_TRIAL_H_
6 #define COMPONENTS_OMNIBOX_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/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 in the corresponding bucket list.
28 // (decayed_count, max_relevance) pair.
29 typedef std::pair<double, int> CountMaxRelevance;
34 // Computes a half-life time decay given the |elapsed_time|.
35 double HalfLifeTimeDecay(const base::TimeDelta& elapsed_time) const;
37 int relevance_cap() const { return relevance_cap_; }
38 void set_relevance_cap(int relevance_cap) {
39 relevance_cap_ = relevance_cap;
42 int half_life_days() const { return half_life_days_; }
43 void set_half_life_days(int half_life_days) {
44 half_life_days_ = half_life_days;
47 std::vector<CountMaxRelevance>& buckets() { return buckets_; }
48 const std::vector<CountMaxRelevance>& buckets() const { return buckets_; }
51 // History matches with relevance score greater or equal to |relevance_cap_|
52 // are not affected by this experiment.
53 // Set to -1, if there is no relevance cap in place and all matches are
54 // subject to demotion.
57 // Half life time for a decayed count as measured since the last visit.
58 // Set to -1 if not used.
61 // The relevance score caps for given decayed count values.
62 // Each pair (decayed_count, max_score) indicates what the maximum relevance
63 // score is of a decayed count equal or greater than decayed_count.
65 // Consider this example:
66 // [(1, 1000), (0.5, 500), (0, 100)]
67 // If decayed count is 2 (which is >= 1), the corresponding match's maximum
68 // relevance will be capped at 1000. In case of 0.5, the score is capped
69 // at 500. Anything below 0.5 is capped at 100.
71 // This list is sorted by the pair's first element in descending order.
72 std::vector<CountMaxRelevance> buckets_;
75 HUPScoringParams() : experimental_scoring_enabled(false) {}
77 bool experimental_scoring_enabled;
79 ScoreBuckets typed_count_buckets;
81 // Used only when the typed count is 0.
82 ScoreBuckets visited_count_buckets;
85 // This class manages the Omnibox field trials.
86 class OmniboxFieldTrial {
88 // A mapping that contains multipliers indicating that matches of the
89 // specified type should have their relevance score multiplied by the
90 // given number. Omitted types are assumed to have multipliers of 1.0.
91 typedef std::map<AutocompleteMatchType::Type, float> DemotionMultipliers;
93 // Activates all dynamic field trials. The main difference between
94 // the autocomplete dynamic and static field trials is that the former
95 // don't require any code changes on the Chrome side as they are controlled
96 // on the server side. Chrome binary simply propagates all necessary
97 // information through the X-Client-Data header.
98 // This method may be called multiple times.
99 static void ActivateDynamicTrials();
101 // Returns a bitmap containing AutocompleteProvider::Type values
102 // that should be disabled in AutocompleteController.
103 // This method simply goes over all autocomplete dynamic field trial groups
104 // and looks for group names like "ProvidersDisabled_NNN" where NNN is
105 // an integer corresponding to a bitmap mask. All extracted bitmaps
106 // are OR-ed together and returned as the final result.
107 static int GetDisabledProviderTypes();
109 // Returns whether the user is in any dynamic field trial where the
110 // group has a the prefix |group_prefix|.
111 static bool HasDynamicFieldTrialGroupPrefix(const char *group_prefix);
113 // ---------------------------------------------------------
114 // For the suggest field trial.
116 // Populates |field_trial_hash| with hashes of the active suggest field trial
118 static void GetActiveSuggestFieldTrialHashes(
119 std::vector<uint32>* field_trial_hash);
121 // ---------------------------------------------------------
122 // For the AutocompleteController "stop timer" field trial.
124 // Returns the duration to be used for the AutocompleteController's stop
125 // timer. Returns the default value of 1.5 seconds if the stop timer
126 // override experiment isn't active or if parsing the experiment-provided
128 static base::TimeDelta StopTimerFieldTrialDuration();
130 // ---------------------------------------------------------
131 // For the ZeroSuggestProvider field trial.
133 // Returns whether the user is in any field trial where the
134 // ZeroSuggestProvider should be used to get suggestions when the
135 // user clicks on the omnibox but has not typed anything yet.
136 static bool InZeroSuggestFieldTrial();
138 // Returns whether the user is in a ZeroSuggest field trial, but should
139 // show most visited URL instead. This is used to compare metrics of
140 // ZeroSuggest and most visited suggestions.
141 static bool InZeroSuggestMostVisitedFieldTrial();
143 // Returns whether the user is in a ZeroSuggest field trial and URL-based
144 // suggestions can continue to appear after the user has started typing.
145 static bool InZeroSuggestAfterTypingFieldTrial();
147 // Returns whether the user is in a ZeroSuggest field trial, but should
148 // show recently searched-for queries instead.
149 static bool InZeroSuggestPersonalizedFieldTrial();
151 // ---------------------------------------------------------
152 // For the ShortcutsScoringMaxRelevance experiment that's part of the
153 // bundled omnibox field trial.
155 // If the user is in an experiment group that, given the provided
156 // |current_page_classification| context, changes the maximum relevance
157 // ShortcutsProvider::CalculateScore() is supposed to assign, extract
158 // that maximum relevance score and put in in |max_relevance|. Returns
159 // true on a successful extraction. CalculateScore()'s return value is
160 // a product of this maximum relevance score and some attenuating factors
161 // that are all between 0 and 1. (Note that Shortcuts results may have
162 // their scores reduced later if the assigned score is higher than allowed
163 // for non-inlineable results. Shortcuts results are not allowed to be
165 static bool ShortcutsScoringMaxRelevance(
166 metrics::OmniboxEventProto::PageClassification
167 current_page_classification,
170 // ---------------------------------------------------------
171 // For the SearchHistory experiment that's part of the bundled omnibox
174 // Returns true if the user is in the experiment group that, given the
175 // provided |current_page_classification| context, scores search history
176 // query suggestions less aggressively so that they don't inline.
177 static bool SearchHistoryPreventInlining(
178 metrics::OmniboxEventProto::PageClassification
179 current_page_classification);
181 // Returns true if the user is in the experiment group that, given the
182 // provided |current_page_classification| context, disables all query
183 // suggestions from search history.
184 static bool SearchHistoryDisable(
185 metrics::OmniboxEventProto::PageClassification
186 current_page_classification);
188 // ---------------------------------------------------------
189 // For the DemoteByType experiment that's part of the bundled omnibox field
192 // If the user is in an experiment group that, in the provided
193 // |current_page_classification| context, demotes the relevance scores
194 // of certain types of matches, populates the |demotions_by_type| map
195 // appropriately. Otherwise, sets |demotions_by_type| to its default
196 // value based on the context.
197 static void GetDemotionsByType(
198 metrics::OmniboxEventProto::PageClassification
199 current_page_classification,
200 DemotionMultipliers* demotions_by_type);
202 // ---------------------------------------------------------
203 // For the HistoryURL provider new scoring experiment that is part of the
204 // bundled omnibox field trial.
206 // Initializes the HUP |scoring_params| based on the active HUP scoring
207 // experiment. If there is no such experiment, this function simply sets
208 // |scoring_params|->experimental_scoring_enabled to false.
209 static void GetExperimentalHUPScoringParams(HUPScoringParams* scoring_params);
211 // For the HQPBookmarkValue experiment that's part of the
212 // bundled omnibox field trial.
214 // Returns the value an untyped visit to a bookmark should receive.
215 // Compare this value with the default of 1 for non-bookmarked untyped
216 // visits to pages and the default of 20 for typed visits. Returns
217 // 10 if the bookmark value experiment isn't active.
218 static int HQPBookmarkValue();
220 // ---------------------------------------------------------
221 // For the HQPAllowMatchInTLD experiment that's part of the
222 // bundled omnibox field trial.
224 // Returns true if HQP should allow an input term to match in the
225 // top level domain (e.g., .com) of a URL. Returns false if the
226 // allow match in TLD experiment isn't active.
227 static bool HQPAllowMatchInTLDValue();
229 // ---------------------------------------------------------
230 // For the HQPAllowMatchInScheme experiment that's part of the
231 // bundled omnibox field trial.
233 // Returns true if HQP should allow an input term to match in the
234 // scheme (e.g., http://) of a URL. Returns false if the allow
235 // match in scheme experiment isn't active.
236 static bool HQPAllowMatchInSchemeValue();
238 // ---------------------------------------------------------
239 // For the BookmarksIndexURLs experiment that's part of the
240 // bundled omnibox field trial.
242 // Returns true if BookmarkIndex should index the URL of bookmarks
243 // (not only the titles) and search for / mark matches in the URLs,
244 // and BookmarkProvider should score bookmarks based on both the
245 // matches in bookmark title and URL. Returns false if the bookmarks
246 // index URLs experiment isn't active.
247 static bool BookmarksIndexURLsValue();
249 // ---------------------------------------------------------
250 // For the DisableInlining experiment that's part of the bundled omnibox
253 // Returns true if AutocompleteResult should prevent any suggestion with
254 // a non-empty |inline_autocomplete| from being the default match. In
255 // other words, prevent an inline autocompletion from appearing as the
256 // top suggestion / within the omnibox itself, reordering matches as
257 // necessary to make this true. Returns false if the experiment isn't
259 static bool DisableInlining();
261 // ---------------------------------------------------------
262 // For the AnswersInSuggest experiment that's part of the bundled omnibox
265 // Returns true if the AnswersInSuggest feature should be enabled causing
266 // query responses such as current weather conditions or stock quotes
267 // to be provided in the Omnibox suggestion list. Considers both the
268 // field trial state as well as the overriding command-line flags.
269 static bool EnableAnswersInSuggest();
271 // ---------------------------------------------------------
272 // For the AddUWYTMatchEvenIfPromotedURLs experiment that's part of the
273 // bundled omnibox field trial.
275 // Returns true if HistoryURL Provider should add the URL-what-you-typed match
276 // (if valid and reasonable) even if the provider has good inline
277 // autocompletions to offer. Normally HistoryURL does not add the UWYT match
278 // if there are good inline autocompletions, as the user could simply hit
279 // backspace to delete the completion and get the what-you-typed match.
280 // However, for the disabling inlining experiment we want to have the UWYT
281 // always explicitly displayed at an option if possible. Returns false if
282 // the experiment isn't active.
283 static bool AddUWYTMatchEvenIfPromotedURLs();
285 // ---------------------------------------------------------
286 // For the DisplayHintTextWhenPossible experiment that's part of the
287 // bundled omnibox field trial.
289 // Returns true if the omnibox should display hint text (Search
290 // <search engine> or type URL) when possible (i.e., the omnibox
291 // is otherwise non-empty).
292 static bool DisplayHintTextWhenPossible();
294 // ---------------------------------------------------------
295 // Exposed publicly for the sake of unittests.
296 static const char kBundledExperimentFieldTrialName[];
297 // Rule names used by the bundled experiment.
298 static const char kShortcutsScoringMaxRelevanceRule[];
299 static const char kSearchHistoryRule[];
300 static const char kDemoteByTypeRule[];
301 static const char kHQPBookmarkValueRule[];
302 static const char kHQPDiscountFrecencyWhenFewVisitsRule[];
303 static const char kHQPAllowMatchInTLDRule[];
304 static const char kHQPAllowMatchInSchemeRule[];
305 static const char kZeroSuggestRule[];
306 static const char kZeroSuggestVariantRule[];
307 static const char kBookmarksIndexURLsRule[];
308 static const char kDisableInliningRule[];
309 static const char kAnswersInSuggestRule[];
310 static const char kAddUWYTMatchEvenIfPromotedURLsRule[];
311 static const char kDisplayHintTextWhenPossibleRule[];
313 // Parameter names used by the HUP new scoring experiments.
314 static const char kHUPNewScoringEnabledParam[];
315 static const char kHUPNewScoringTypedCountRelevanceCapParam[];
316 static const char kHUPNewScoringTypedCountHalfLifeTimeParam[];
317 static const char kHUPNewScoringTypedCountScoreBucketsParam[];
318 static const char kHUPNewScoringVisitedCountRelevanceCapParam[];
319 static const char kHUPNewScoringVisitedCountHalfLifeTimeParam[];
320 static const char kHUPNewScoringVisitedCountScoreBucketsParam[];
323 friend class OmniboxFieldTrialTest;
325 // The bundled omnibox experiment comes with a set of parameters
326 // (key-value pairs). Each key indicates a certain rule that applies in
327 // a certain context. The value indicates what the consequences of
328 // applying the rule are. For example, the value of a SearchHistory rule
329 // in the context of a search results page might indicate that we should
330 // prevent search history matches from inlining.
332 // This function returns the value associated with the |rule| that applies
333 // in the current context (which currently consists of |page_classification|
334 // and whether Instant Extended is enabled). If no such rule exists in the
335 // current context, fall back to the rule in various wildcard contexts and
336 // return its value if found. If the rule remains unfound in the global
337 // context, returns the empty string. For more details, including how we
338 // prioritize different wildcard contexts, see the implementation. How to
339 // interpret the value is left to the caller; this is rule-dependent.
340 static std::string GetValueForRuleInContext(
341 const std::string& rule,
342 metrics::OmniboxEventProto::PageClassification page_classification);
344 DISALLOW_IMPLICIT_CONSTRUCTORS(OmniboxFieldTrial);
347 #endif // COMPONENTS_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_