| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_ | |
| 6 #define CHROME_BROWSER_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 #include <string> | |
| 10 #include <vector> | |
| 11 | |
| 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" | |
| 16 | |
| 17 namespace base { | |
| 18 class TimeDelta; | |
| 19 } | |
| 20 | |
| 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. | |
| 26 class ScoreBuckets { | |
| 27 public: | |
| 28 // (decayed_count, max_relevance) pair. | |
| 29 typedef std::pair<double, int> CountMaxRelevance; | |
| 30 | |
| 31 ScoreBuckets(); | |
| 32 ~ScoreBuckets(); | |
| 33 | |
| 34 // Computes a half-life time decay given the |elapsed_time|. | |
| 35 double HalfLifeTimeDecay(const base::TimeDelta& elapsed_time) const; | |
| 36 | |
| 37 int relevance_cap() const { return relevance_cap_; } | |
| 38 void set_relevance_cap(int relevance_cap) { | |
| 39 relevance_cap_ = relevance_cap; | |
| 40 } | |
| 41 | |
| 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; | |
| 45 } | |
| 46 | |
| 47 std::vector<CountMaxRelevance>& buckets() { return buckets_; } | |
| 48 const std::vector<CountMaxRelevance>& buckets() const { return buckets_; } | |
| 49 | |
| 50 private: | |
| 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. | |
| 55 int relevance_cap_; | |
| 56 | |
| 57 // Half life time for a decayed count as measured since the last visit. | |
| 58 // Set to -1 if not used. | |
| 59 int half_life_days_; | |
| 60 | |
| 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. | |
| 64 // | |
| 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. | |
| 70 // | |
| 71 // This list is sorted by the pair's first element in descending order. | |
| 72 std::vector<CountMaxRelevance> buckets_; | |
| 73 }; | |
| 74 | |
| 75 HUPScoringParams() : experimental_scoring_enabled(false) {} | |
| 76 | |
| 77 bool experimental_scoring_enabled; | |
| 78 | |
| 79 ScoreBuckets typed_count_buckets; | |
| 80 | |
| 81 // Used only when the typed count is 0. | |
| 82 ScoreBuckets visited_count_buckets; | |
| 83 }; | |
| 84 | |
| 85 // This class manages the Omnibox field trials. | |
| 86 class OmniboxFieldTrial { | |
| 87 public: | |
| 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; | |
| 92 | |
| 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(); | |
| 100 | |
| 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(); | |
| 108 | |
| 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); | |
| 112 | |
| 113 // --------------------------------------------------------- | |
| 114 // For the suggest field trial. | |
| 115 | |
| 116 // Populates |field_trial_hash| with hashes of the active suggest field trial | |
| 117 // names, if any. | |
| 118 static void GetActiveSuggestFieldTrialHashes( | |
| 119 std::vector<uint32>* field_trial_hash); | |
| 120 | |
| 121 // --------------------------------------------------------- | |
| 122 // For the AutocompleteController "stop timer" field trial. | |
| 123 | |
| 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 | |
| 127 // duration fails. | |
| 128 static base::TimeDelta StopTimerFieldTrialDuration(); | |
| 129 | |
| 130 // --------------------------------------------------------- | |
| 131 // For the ZeroSuggestProvider field trial. | |
| 132 | |
| 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(); | |
| 137 | |
| 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(); | |
| 142 | |
| 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(); | |
| 146 | |
| 147 // Returns whether the user is in a ZeroSuggest field trial, but should | |
| 148 // show recently searched-for queries instead. | |
| 149 static bool InZeroSuggestPersonalizedFieldTrial(); | |
| 150 | |
| 151 // --------------------------------------------------------- | |
| 152 // For the ShortcutsScoringMaxRelevance experiment that's part of the | |
| 153 // bundled omnibox field trial. | |
| 154 | |
| 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 | |
| 164 // inlined.) | |
| 165 static bool ShortcutsScoringMaxRelevance( | |
| 166 metrics::OmniboxEventProto::PageClassification | |
| 167 current_page_classification, | |
| 168 int* max_relevance); | |
| 169 | |
| 170 // --------------------------------------------------------- | |
| 171 // For the SearchHistory experiment that's part of the bundled omnibox | |
| 172 // field trial. | |
| 173 | |
| 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); | |
| 180 | |
| 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); | |
| 187 | |
| 188 // --------------------------------------------------------- | |
| 189 // For the DemoteByType experiment that's part of the bundled omnibox field | |
| 190 // trial. | |
| 191 | |
| 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); | |
| 201 | |
| 202 // --------------------------------------------------------- | |
| 203 // For the HistoryURL provider new scoring experiment that is part of the | |
| 204 // bundled omnibox field trial. | |
| 205 | |
| 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); | |
| 210 | |
| 211 // For the HQPBookmarkValue experiment that's part of the | |
| 212 // bundled omnibox field trial. | |
| 213 | |
| 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(); | |
| 219 | |
| 220 // --------------------------------------------------------- | |
| 221 // For the HQPAllowMatchInTLD experiment that's part of the | |
| 222 // bundled omnibox field trial. | |
| 223 | |
| 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(); | |
| 228 | |
| 229 // --------------------------------------------------------- | |
| 230 // For the HQPAllowMatchInScheme experiment that's part of the | |
| 231 // bundled omnibox field trial. | |
| 232 | |
| 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(); | |
| 237 | |
| 238 // --------------------------------------------------------- | |
| 239 // For the BookmarksIndexURLs experiment that's part of the | |
| 240 // bundled omnibox field trial. | |
| 241 | |
| 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(); | |
| 248 | |
| 249 // --------------------------------------------------------- | |
| 250 // For the DisableInlining experiment that's part of the bundled omnibox | |
| 251 // field trial. | |
| 252 | |
| 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 | |
| 258 // active. | |
| 259 static bool DisableInlining(); | |
| 260 | |
| 261 // --------------------------------------------------------- | |
| 262 // For the AnswersInSuggest experiment that's part of the bundled omnibox | |
| 263 // field trial. | |
| 264 | |
| 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(); | |
| 270 | |
| 271 // --------------------------------------------------------- | |
| 272 // For the AddUWYTMatchEvenIfPromotedURLs experiment that's part of the | |
| 273 // bundled omnibox field trial. | |
| 274 | |
| 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(); | |
| 284 | |
| 285 // --------------------------------------------------------- | |
| 286 // For the DisplayHintTextWhenPossible experiment that's part of the | |
| 287 // bundled omnibox field trial. | |
| 288 | |
| 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(); | |
| 293 | |
| 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[]; | |
| 312 | |
| 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[]; | |
| 321 | |
| 322 private: | |
| 323 friend class OmniboxFieldTrialTest; | |
| 324 | |
| 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. | |
| 331 // | |
| 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); | |
| 343 | |
| 344 DISALLOW_IMPLICIT_CONSTRUCTORS(OmniboxFieldTrial); | |
| 345 }; | |
| 346 | |
| 347 #endif // CHROME_BROWSER_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_ | |
| OLD | NEW |