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.
4 
5 #include "components/omnibox/browser/omnibox_field_trial.h"
6 
7 #include <algorithm>
8 #include <cmath>
9 #include <functional>
10 #include <string>
11 
12 #include "base/command_line.h"
13 #include "base/feature_list.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/metrics/field_trial_params.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h"
19 #include "base/system/sys_info.h"
20 #include "base/time/time.h"
21 #include "base/trace_event/memory_usage_estimator.h"
22 #include "build/build_config.h"
23 #include "components/history/core/browser/url_database.h"
24 #include "components/omnibox/browser/url_index_private_data.h"
25 #include "components/omnibox/common/omnibox_features.h"
26 #include "components/search/search.h"
27 #include "components/variations/active_field_trials.h"
28 #include "components/variations/hashing.h"
29 #include "components/variations/variations_associated_data.h"
30 #include "third_party/metrics_proto/omnibox_event.pb.h"
31 #include "ui/base/pointer/touch_ui_controller.h"
32 
33 using metrics::OmniboxEventProto;
34 
35 namespace {
36 
37 typedef std::map<std::string, std::string> VariationParams;
38 typedef HUPScoringParams::ScoreBuckets ScoreBuckets;
39 
40 // Field trial names.
41 const char kStopTimerFieldTrialName[] = "OmniboxStopTimer";
42 
InitializeBucketsFromString(const std::string & bucket_string,ScoreBuckets * score_buckets)43 void InitializeBucketsFromString(const std::string& bucket_string,
44                                  ScoreBuckets* score_buckets) {
45   // Clear the buckets.
46   score_buckets->buckets().clear();
47   base::StringPairs kv_pairs;
48   if (base::SplitStringIntoKeyValuePairs(bucket_string, ':', ',', &kv_pairs)) {
49     for (base::StringPairs::const_iterator it = kv_pairs.begin();
50          it != kv_pairs.end(); ++it) {
51       ScoreBuckets::CountMaxRelevance bucket;
52       base::StringToDouble(it->first, &bucket.first);
53       base::StringToInt(it->second, &bucket.second);
54       score_buckets->buckets().push_back(bucket);
55     }
56     std::sort(score_buckets->buckets().begin(),
57               score_buckets->buckets().end(),
58               std::greater<ScoreBuckets::CountMaxRelevance>());
59   }
60 }
61 
InitializeScoreBuckets(const VariationParams & params,const char * relevance_cap_param,const char * half_life_param,const char * score_buckets_param,const char * use_decay_factor_param,ScoreBuckets * score_buckets)62 void InitializeScoreBuckets(const VariationParams& params,
63                             const char* relevance_cap_param,
64                             const char* half_life_param,
65                             const char* score_buckets_param,
66                             const char* use_decay_factor_param,
67                             ScoreBuckets* score_buckets) {
68   auto it = params.find(relevance_cap_param);
69   if (it != params.end()) {
70     int relevance_cap;
71     if (base::StringToInt(it->second, &relevance_cap))
72       score_buckets->set_relevance_cap(relevance_cap);
73   }
74 
75   it = params.find(use_decay_factor_param);
76   if (it != params.end()) {
77     int use_decay_factor;
78     if (base::StringToInt(it->second, &use_decay_factor))
79       score_buckets->set_use_decay_factor(use_decay_factor != 0);
80   }
81 
82   it = params.find(half_life_param);
83   if (it != params.end()) {
84     int half_life_days;
85     if (base::StringToInt(it->second, &half_life_days))
86       score_buckets->set_half_life_days(half_life_days);
87   }
88 
89   it = params.find(score_buckets_param);
90   if (it != params.end()) {
91     // The value of the score bucket is a comma-separated list of
92     // {DecayedCount/DecayedFactor + ":" + MaxRelevance}.
93     InitializeBucketsFromString(it->second, score_buckets);
94   }
95 }
96 
97 // Background and implementation details:
98 //
99 // Each experiment group in any field trial can come with an optional set of
100 // parameters (key-value pairs).  In the bundled omnibox experiment
101 // (kBundledExperimentFieldTrialName), each experiment group comes with a
102 // list of parameters in the form:
103 //   key=<Rule>:
104 //       <OmniboxEventProto::PageClassification (as an int)>:
105 //       <whether Instant Extended is enabled (as a 1 or 0)>
106 //     (note that there are no linebreaks in keys; this format is for
107 //      presentation only>
108 //   value=<arbitrary string>
109 // Both the OmniboxEventProto::PageClassification and the Instant Extended
110 // entries can be "*", which means this rule applies for all values of the
111 // matching portion of the context.
112 // One example parameter is
113 //   key=SearchHistory:6:1
114 //   value=PreventInlining
115 // This means in page classification context 6 (a search result page doing
116 // search term replacement) with Instant Extended enabled, the SearchHistory
117 // experiment should PreventInlining.
118 //
119 // When an exact match to the rule in the current context is missing, we
120 // give preference to a wildcard rule that matches the instant extended
121 // context over a wildcard rule that matches the page classification
122 // context.  Hopefully, though, users will write their field trial configs
123 // so as not to rely on this fall back order.
124 //
125 // In short, this function tries to find the value associated with key
126 // |rule|:|page_classification|:|instant_extended|, failing that it looks up
127 // |rule|:*:|instant_extended|, failing that it looks up
128 // |rule|:|page_classification|:*, failing that it looks up |rule|:*:*,
129 // and failing that it returns the empty string.
GetValueForRuleInContextFromVariationParams(const std::map<std::string,std::string> & params,const std::string & rule,OmniboxEventProto::PageClassification page_classification)130 std::string GetValueForRuleInContextFromVariationParams(
131     const std::map<std::string, std::string>& params,
132     const std::string& rule,
133     OmniboxEventProto::PageClassification page_classification) {
134   if (params.empty())
135     return std::string();
136 
137   const std::string page_classification_str =
138       base::NumberToString(static_cast<int>(page_classification));
139   const std::string instant_extended =
140       search::IsInstantExtendedAPIEnabled() ? "1" : "0";
141   // Look up rule in this exact context.
142   VariationParams::const_iterator it = params.find(
143       rule + ":" + page_classification_str + ":" + instant_extended);
144   if (it != params.end())
145     return it->second;
146   // Fall back to the global page classification context.
147   it = params.find(rule + ":*:" + instant_extended);
148   if (it != params.end())
149     return it->second;
150   // Fall back to the global instant extended context.
151   it = params.find(rule + ":" + page_classification_str + ":*");
152   if (it != params.end())
153     return it->second;
154   // Look up rule in the global context.
155   it = params.find(rule + ":*:*");
156   return (it != params.end()) ? it->second : std::string();
157 }
158 
159 }  // namespace
160 
ScoreBuckets()161 HUPScoringParams::ScoreBuckets::ScoreBuckets()
162     : relevance_cap_(-1),
163       half_life_days_(-1),
164       use_decay_factor_(false) {
165 }
166 
167 HUPScoringParams::ScoreBuckets::ScoreBuckets(const ScoreBuckets& other) =
168     default;
169 
~ScoreBuckets()170 HUPScoringParams::ScoreBuckets::~ScoreBuckets() {
171 }
172 
EstimateMemoryUsage() const173 size_t HUPScoringParams::ScoreBuckets::EstimateMemoryUsage() const {
174   return base::trace_event::EstimateMemoryUsage(buckets_);
175 }
176 
HalfLifeTimeDecay(const base::TimeDelta & elapsed_time) const177 double HUPScoringParams::ScoreBuckets::HalfLifeTimeDecay(
178     const base::TimeDelta& elapsed_time) const {
179   double time_ms;
180   if ((half_life_days_ <= 0) ||
181       ((time_ms = elapsed_time.InMillisecondsF()) <= 0))
182     return 1.0;
183 
184   const double half_life_intervals =
185       time_ms / base::TimeDelta::FromDays(half_life_days_).InMillisecondsF();
186   return pow(2.0, -half_life_intervals);
187 }
188 
EstimateMemoryUsage() const189 size_t HUPScoringParams::EstimateMemoryUsage() const {
190   size_t res = 0;
191 
192   res += base::trace_event::EstimateMemoryUsage(typed_count_buckets);
193   res += base::trace_event::EstimateMemoryUsage(visited_count_buckets);
194 
195   return res;
196 }
197 
GetDisabledProviderTypes()198 int OmniboxFieldTrial::GetDisabledProviderTypes() {
199   const std::string& types_string = variations::GetVariationParamValue(
200       kBundledExperimentFieldTrialName,
201       kDisableProvidersRule);
202   int types = 0;
203   if (types_string.empty() || !base::StringToInt(types_string, &types)) {
204     return 0;
205   }
206   return types;
207 }
208 
GetActiveSuggestFieldTrialHashes(std::vector<uint32_t> * field_trial_hashes)209 void OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(
210     std::vector<uint32_t>* field_trial_hashes) {
211   field_trial_hashes->clear();
212   if (base::FieldTrialList::TrialExists(kBundledExperimentFieldTrialName)) {
213     field_trial_hashes->push_back(
214         variations::HashName(kBundledExperimentFieldTrialName));
215   }
216 }
217 
StopTimerFieldTrialDuration()218 base::TimeDelta OmniboxFieldTrial::StopTimerFieldTrialDuration() {
219   int stop_timer_ms;
220   if (base::StringToInt(
221           base::FieldTrialList::FindFullName(kStopTimerFieldTrialName),
222           &stop_timer_ms))
223     return base::TimeDelta::FromMilliseconds(stop_timer_ms);
224   return base::TimeDelta::FromMilliseconds(1500);
225 }
226 
GetLocalHistoryZeroSuggestAgeThreshold()227 base::Time OmniboxFieldTrial::GetLocalHistoryZeroSuggestAgeThreshold() {
228   // If new search features are disabled, return the default value.
229   if (!base::FeatureList::IsEnabled(omnibox::kNewSearchFeatures)) {
230     return history::AutocompleteAgeThreshold();
231   }
232 
233   std::string param_value = base::GetFieldTrialParamValueByFeature(
234       omnibox::kOmniboxLocalZeroSuggestAgeThreshold,
235       OmniboxFieldTrial::kOmniboxLocalZeroSuggestAgeThresholdParam);
236 
237   // If the field trial param is not found or cannot be parsed to an unsigned
238   // integer, return the default value.
239   unsigned int param_value_as_int = 0;
240   if (!base::StringToUint(param_value, &param_value_as_int)) {
241     return history::AutocompleteAgeThreshold();
242   }
243 
244   return (base::Time::Now() - base::TimeDelta::FromDays(param_value_as_int));
245 }
246 
ShortcutsScoringMaxRelevance(OmniboxEventProto::PageClassification current_page_classification,int * max_relevance)247 bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
248     OmniboxEventProto::PageClassification current_page_classification,
249     int* max_relevance) {
250   // The value of the rule is a string that encodes an integer containing
251   // the max relevance.
252   const std::string& max_relevance_str =
253       OmniboxFieldTrial::internal::GetValueForRuleInContext(
254           kShortcutsScoringMaxRelevanceRule, current_page_classification);
255   if (max_relevance_str.empty())
256     return false;
257   if (!base::StringToInt(max_relevance_str, max_relevance))
258     return false;
259   return true;
260 }
261 
SearchHistoryPreventInlining(OmniboxEventProto::PageClassification current_page_classification)262 bool OmniboxFieldTrial::SearchHistoryPreventInlining(
263     OmniboxEventProto::PageClassification current_page_classification) {
264   return OmniboxFieldTrial::internal::GetValueForRuleInContext(
265              kSearchHistoryRule, current_page_classification) ==
266          "PreventInlining";
267 }
268 
SearchHistoryDisable(OmniboxEventProto::PageClassification current_page_classification)269 bool OmniboxFieldTrial::SearchHistoryDisable(
270     OmniboxEventProto::PageClassification current_page_classification) {
271   return OmniboxFieldTrial::internal::GetValueForRuleInContext(
272              kSearchHistoryRule, current_page_classification) == "Disable";
273 }
274 
GetDemotionsByType(OmniboxEventProto::PageClassification current_page_classification,DemotionMultipliers * demotions_by_type)275 void OmniboxFieldTrial::GetDemotionsByType(
276     OmniboxEventProto::PageClassification current_page_classification,
277     DemotionMultipliers* demotions_by_type) {
278   demotions_by_type->clear();
279 
280   // Explicitly check whether the feature is enabled before calling
281   // |GetValueForRuleInContextByFeature| because it is possible for
282   // |GetValueForRuleInContextByFeature| to return an empty string even if the
283   // feature is enabled, and we don't want to fallback to
284   // |GetValueForRuleInContext| in this case.
285   std::string demotion_rule =
286       base::FeatureList::IsEnabled(omnibox::kOmniboxDemoteByType)
287           ? OmniboxFieldTrial::internal::GetValueForRuleInContextByFeature(
288                 omnibox::kOmniboxDemoteByType, kDemoteByTypeRule,
289                 current_page_classification)
290           : OmniboxFieldTrial::internal::GetValueForRuleInContext(
291                 kDemoteByTypeRule, current_page_classification);
292   // If there is no demotion rule for this context, then use the default
293   // value for that context.
294   if (demotion_rule.empty()) {
295     // This rule demotes URLs as strongly as possible without violating user
296     // expectations.  In particular, for URL-seeking inputs, if the user would
297     // likely expect a URL first (i.e., it would be inline autocompleted), then
298     // that URL will still score strongly enough to be first.  This is done
299     // using a demotion multipler of 0.61.  If a URL would get a score high
300     // enough to be inline autocompleted (1400+), even after demotion it will
301     // score above 850 ( 1400 * 0.61 > 850).  850 is the maximum score for
302     // queries when the input has been detected as URL-seeking.
303 #if defined(OS_ANDROID)
304     if (current_page_classification == OmniboxEventProto::
305         SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT)
306       demotion_rule = "1:61,2:61,3:61,4:61,16:61,24:61";
307 #endif
308     if (current_page_classification ==
309             OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS ||
310         current_page_classification == OmniboxEventProto::NTP_REALBOX) {
311       demotion_rule = "1:10,2:10,3:10,4:10,5:10,16:10,17:10,24:10";
312     }
313   }
314 
315   // The value of the DemoteByType rule is a comma-separated list of
316   // {ResultType + ":" + Number} where ResultType is an AutocompleteMatchType::
317   // Type enum represented as an integer and Number is an integer number
318   // between 0 and 100 inclusive.   Relevance scores of matches of that result
319   // type are multiplied by Number / 100.  100 means no change.
320   base::StringPairs kv_pairs;
321   if (base::SplitStringIntoKeyValuePairs(demotion_rule, ':', ',', &kv_pairs)) {
322     for (base::StringPairs::const_iterator it = kv_pairs.begin();
323          it != kv_pairs.end(); ++it) {
324       // This is a best-effort conversion; we trust the hand-crafted parameters
325       // downloaded from the server to be perfect.  There's no need to handle
326       // errors smartly.
327       int k, v;
328       base::StringToInt(it->first, &k);
329       base::StringToInt(it->second, &v);
330       (*demotions_by_type)[static_cast<AutocompleteMatchType::Type>(k)] =
331           static_cast<float>(v) / 100.0f;
332     }
333   }
334 }
335 
GetProviderMaxMatches(AutocompleteProvider::Type provider)336 size_t OmniboxFieldTrial::GetProviderMaxMatches(
337     AutocompleteProvider::Type provider) {
338   size_t default_max_matches_per_provider = 3;
339 
340   // If new search features are disabled, ignore the parameter and use the
341   // default value.
342   if (!base::FeatureList::IsEnabled(omnibox::kNewSearchFeatures))
343     return default_max_matches_per_provider;
344 
345   std::string param_value = base::GetFieldTrialParamValueByFeature(
346       omnibox::kUIExperimentMaxAutocompleteMatches,
347       OmniboxFieldTrial::kUIMaxAutocompleteMatchesByProviderParam);
348 
349   // If the experiment param specifies a max results for |provider|, return the
350   // specified limit.
351   // E.g., if param_value = '3:2' and provider = 3, return 2.
352   // Otherwise, if the experiment param specifies a default value for
353   // unspecified providers, return the default value.
354   // E.g., if param_value = '3:3,*:4' and provider = 1, return 4,
355   // Otherwise, return |default_max_matches_per_provider|.
356   base::StringPairs kv_pairs;
357   if (base::SplitStringIntoKeyValuePairs(param_value, ':', ',', &kv_pairs)) {
358     for (const auto& kv_pair : kv_pairs) {
359       int k;
360       base::StringToInt(kv_pair.first, &k);
361       size_t v;
362       base::StringToSizeT(kv_pair.second, &v);
363 
364       if (kv_pair.first == "*")
365         default_max_matches_per_provider = v;
366       else if (k == provider)
367         return v;
368     }
369   }
370 
371   return default_max_matches_per_provider;
372 }
373 
IsMaxURLMatchesFeatureEnabled()374 bool OmniboxFieldTrial::IsMaxURLMatchesFeatureEnabled() {
375   // If new search features are disabled, return the default/launched value for
376   // the respective platforms, independent of the state of the Feature.
377   if (!base::FeatureList::IsEnabled(omnibox::kNewSearchFeatures))
378     return omnibox::kOmniboxMaxURLMatchesEnabledByDefault;
379 
380   return base::FeatureList::IsEnabled(omnibox::kOmniboxMaxURLMatches);
381 }
382 
GetMaxURLMatches()383 size_t OmniboxFieldTrial::GetMaxURLMatches() {
384   constexpr size_t kDefaultMaxURLMatches = 7;
385 
386   // If new search features are disabled, ignore the parameter and use the
387   // default value.
388   if (!base::FeatureList::IsEnabled(omnibox::kNewSearchFeatures))
389     return kDefaultMaxURLMatches;
390 
391   return base::GetFieldTrialParamByFeatureAsInt(
392       omnibox::kOmniboxMaxURLMatches,
393       OmniboxFieldTrial::kOmniboxMaxURLMatchesParam, kDefaultMaxURLMatches);
394 }
395 
GetDefaultHUPScoringParams(HUPScoringParams * scoring_params)396 void OmniboxFieldTrial::GetDefaultHUPScoringParams(
397     HUPScoringParams* scoring_params) {
398   ScoreBuckets* type_score_buckets = &scoring_params->typed_count_buckets;
399   type_score_buckets->set_half_life_days(30);
400   type_score_buckets->set_use_decay_factor(false);
401   // Default typed count buckets based on decayed typed count. The
402   // values here are based on the results of field trials to determine what
403   // maximized overall result quality.
404   const std::string& typed_count_score_buckets_str =
405       "1.0:1413,0.97:1390,0.93:1360,0.85:1340,0.72:1320,0.50:1250,0.0:1203";
406   InitializeBucketsFromString(typed_count_score_buckets_str,
407                               type_score_buckets);
408 
409   ScoreBuckets* visit_score_buckets = &scoring_params->visited_count_buckets;
410   visit_score_buckets->set_half_life_days(30);
411   visit_score_buckets->set_use_decay_factor(false);
412   // Buckets based on visit count.  Like the typed count buckets above, the
413   // values here were chosen based on field trials.  Note that when a URL hasn't
414   // been visited in the last 30 days, we clamp its score to 100, which
415   // basically demotes it below any other results in the dropdown.
416   const std::string& visit_count_score_buckets_str = "4.0:790,0.5:590,0.0:100";
417   InitializeBucketsFromString(visit_count_score_buckets_str,
418                               visit_score_buckets);
419 }
420 
GetExperimentalHUPScoringParams(HUPScoringParams * scoring_params)421 void OmniboxFieldTrial::GetExperimentalHUPScoringParams(
422     HUPScoringParams* scoring_params) {
423   VariationParams params;
424   if (!variations::GetVariationParams(kBundledExperimentFieldTrialName,
425                                       &params))
426     return;
427 
428   InitializeScoreBuckets(params, kHUPNewScoringTypedCountRelevanceCapParam,
429                          kHUPNewScoringTypedCountHalfLifeTimeParam,
430                          kHUPNewScoringTypedCountScoreBucketsParam,
431                          kHUPNewScoringTypedCountUseDecayFactorParam,
432                          &scoring_params->typed_count_buckets);
433   InitializeScoreBuckets(params, kHUPNewScoringVisitedCountRelevanceCapParam,
434                          kHUPNewScoringVisitedCountHalfLifeTimeParam,
435                          kHUPNewScoringVisitedCountScoreBucketsParam,
436                          kHUPNewScoringVisitedCountUseDecayFactorParam,
437                          &scoring_params->visited_count_buckets);
438 }
439 
HQPBookmarkValue()440 float OmniboxFieldTrial::HQPBookmarkValue() {
441   std::string bookmark_value_str =
442       variations::GetVariationParamValue(kBundledExperimentFieldTrialName,
443                                          kHQPBookmarkValueRule);
444   if (bookmark_value_str.empty())
445     return 10;
446   // This is a best-effort conversion; we trust the hand-crafted parameters
447   // downloaded from the server to be perfect.  There's no need for handle
448   // errors smartly.
449   double bookmark_value;
450   base::StringToDouble(bookmark_value_str, &bookmark_value);
451   return bookmark_value;
452 }
453 
HQPAllowMatchInTLDValue()454 bool OmniboxFieldTrial::HQPAllowMatchInTLDValue() {
455   return variations::GetVariationParamValue(
456       kBundledExperimentFieldTrialName,
457       kHQPAllowMatchInTLDRule) == "true";
458 }
459 
HQPAllowMatchInSchemeValue()460 bool OmniboxFieldTrial::HQPAllowMatchInSchemeValue() {
461   return variations::GetVariationParamValue(
462       kBundledExperimentFieldTrialName,
463       kHQPAllowMatchInSchemeRule) == "true";
464 }
465 
GetSuggestPollingStrategy(bool * from_last_keystroke,int * polling_delay_ms)466 void OmniboxFieldTrial::GetSuggestPollingStrategy(bool* from_last_keystroke,
467                                                   int* polling_delay_ms) {
468   *from_last_keystroke = variations::GetVariationParamValue(
469       kBundledExperimentFieldTrialName,
470       kMeasureSuggestPollingDelayFromLastKeystrokeRule) == "true";
471 
472   const std::string& polling_delay_string = variations::GetVariationParamValue(
473       kBundledExperimentFieldTrialName,
474       kSuggestPollingDelayMsRule);
475   if (polling_delay_string.empty() ||
476       !base::StringToInt(polling_delay_string, polling_delay_ms) ||
477       (*polling_delay_ms <= 0)) {
478     *polling_delay_ms = kDefaultMinimumTimeBetweenSuggestQueriesMs;
479   }
480 }
481 
HQPExperimentalScoringBuckets()482 std::string OmniboxFieldTrial::HQPExperimentalScoringBuckets() {
483   return variations::GetVariationParamValue(
484       kBundledExperimentFieldTrialName,
485       kHQPExperimentalScoringBucketsParam);
486 }
487 
HQPExperimentalTopicalityThreshold()488 float OmniboxFieldTrial::HQPExperimentalTopicalityThreshold() {
489   std::string topicality_threshold_str = variations::GetVariationParamValue(
490       kBundledExperimentFieldTrialName,
491       kHQPExperimentalScoringTopicalityThresholdParam);
492 
493   double topicality_threshold;
494   if (topicality_threshold_str.empty() ||
495       !base::StringToDouble(topicality_threshold_str, &topicality_threshold))
496     return 0.5f;
497 
498   return static_cast<float>(topicality_threshold);
499 }
500 
MaxNumHQPUrlsIndexedAtStartup()501 int OmniboxFieldTrial::MaxNumHQPUrlsIndexedAtStartup() {
502   const char* param = kMaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevicesParam;
503   const bool is_low_end_device = base::SysInfo::IsLowEndDevice();
504   if (is_low_end_device)
505     param = kMaxNumHQPUrlsIndexedAtStartupOnLowEndDevicesParam;
506   std::string param_value(variations::GetVariationParamValue(
507       kBundledExperimentFieldTrialName, param));
508   int num_urls;
509   if (base::StringToInt(param_value, &num_urls))
510     return num_urls;
511 
512 #if defined(OS_ANDROID)
513   // Limits on Android are chosen based on experiment results. See
514   // crbug.com/715852#c18.
515   constexpr int kMaxNumHQPUrlsIndexedAtStartupOnLowEndDevices = 100;
516   constexpr int kMaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevices = 1000;
517   if (is_low_end_device)
518     return kMaxNumHQPUrlsIndexedAtStartupOnLowEndDevices;
519   return kMaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevices;
520 #else
521   // Use 20,000 entries as a safety cap for users with spammed history,
522   // such as users who were stuck in a redirect loop with autogenerated URLs.
523   // This limit will only affect 0.01% of Windows users. crbug.com/750845.
524   return 20000;
525 #endif  // defined(OS_ANDROID)
526 }
527 
HQPMaxVisitsToScore()528 size_t OmniboxFieldTrial::HQPMaxVisitsToScore() {
529   std::string max_visits_str = variations::GetVariationParamValue(
530       kBundledExperimentFieldTrialName, kHQPMaxVisitsToScoreRule);
531   constexpr size_t kDefaultMaxVisitsToScore = 10;
532   static_assert(
533       URLIndexPrivateData::kMaxVisitsToStoreInCache >= kDefaultMaxVisitsToScore,
534       "HQP should store at least as many visits as it expects to score");
535   if (max_visits_str.empty())
536     return kDefaultMaxVisitsToScore;
537   // This is a best-effort conversion; we trust the hand-crafted parameters
538   // downloaded from the server to be perfect.  There's no need for handle
539   // errors smartly.
540   size_t max_visits_value;
541   base::StringToSizeT(max_visits_str, &max_visits_value);
542   return max_visits_value;
543 }
544 
HQPTypedValue()545 float OmniboxFieldTrial::HQPTypedValue() {
546   std::string typed_value_str = variations::GetVariationParamValue(
547       kBundledExperimentFieldTrialName, kHQPTypedValueRule);
548   if (typed_value_str.empty())
549     return 1.5;
550   // This is a best-effort conversion; we trust the hand-crafted parameters
551   // downloaded from the server to be perfect.  There's no need for handle
552   // errors smartly.
553   double typed_value;
554   base::StringToDouble(typed_value_str, &typed_value);
555   return typed_value;
556 }
557 
HQPNumMatchesScores()558 OmniboxFieldTrial::NumMatchesScores OmniboxFieldTrial::HQPNumMatchesScores() {
559   std::string str = variations::GetVariationParamValue(
560       kBundledExperimentFieldTrialName, kHQPNumMatchesScoresRule);
561   static constexpr char kDefaultNumMatchesScores[] = "1:3,2:2.5,3:2,4:1.5";
562   if (str.empty())
563     str = kDefaultNumMatchesScores;
564   // The parameter is a comma-separated list of (number, value) pairs such as
565   // listed above.
566   // This is a best-effort conversion; we trust the hand-crafted parameters
567   // downloaded from the server to be perfect.  There's no need to handle
568   // errors smartly.
569   base::StringPairs kv_pairs;
570   if (!base::SplitStringIntoKeyValuePairs(str, ':', ',', &kv_pairs))
571     return NumMatchesScores{};
572   NumMatchesScores num_matches_scores(kv_pairs.size());
573   for (size_t i = 0; i < kv_pairs.size(); ++i) {
574     base::StringToSizeT(kv_pairs[i].first, &num_matches_scores[i].first);
575     // The input must be sorted by number of matches.
576     DCHECK((i == 0) ||
577            (num_matches_scores[i].first > num_matches_scores[i - 1].first));
578     base::StringToDouble(kv_pairs[i].second, &num_matches_scores[i].second);
579   }
580   return num_matches_scores;
581 }
582 
HQPNumTitleWordsToAllow()583 size_t OmniboxFieldTrial::HQPNumTitleWordsToAllow() {
584   // The value of the rule is a string that encodes an integer (actually
585   // size_t) containing the number of words.
586   size_t num_title_words;
587   if (!base::StringToSizeT(
588           variations::GetVariationParamValue(kBundledExperimentFieldTrialName,
589                                              kHQPNumTitleWordsRule),
590           &num_title_words))
591     return 20;
592   return num_title_words;
593 }
594 
HQPAlsoDoHUPLikeScoring()595 bool OmniboxFieldTrial::HQPAlsoDoHUPLikeScoring() {
596   return variations::GetVariationParamValue(
597       kBundledExperimentFieldTrialName,
598       kHQPAlsoDoHUPLikeScoringRule) == "true";
599 }
600 
HUPSearchDatabase()601 bool OmniboxFieldTrial::HUPSearchDatabase() {
602   const std::string& value = variations::GetVariationParamValue(
603       kBundledExperimentFieldTrialName,
604       kHUPSearchDatabaseRule);
605   return value.empty() || (value == "true");
606 }
607 
KeywordScoreForSufficientlyCompleteMatch()608 int OmniboxFieldTrial::KeywordScoreForSufficientlyCompleteMatch() {
609   std::string value_str = variations::GetVariationParamValue(
610       kBundledExperimentFieldTrialName,
611       kKeywordScoreForSufficientlyCompleteMatchRule);
612   if (value_str.empty())
613     return -1;
614   // This is a best-effort conversion; we trust the hand-crafted parameters
615   // downloaded from the server to be perfect.  There's no need for handle
616   // errors smartly.
617   int value;
618   base::StringToInt(value_str, &value);
619   return value;
620 }
621 
622 OmniboxFieldTrial::EmphasizeTitlesCondition
GetEmphasizeTitlesConditionForInput(const AutocompleteInput & input)623 OmniboxFieldTrial::GetEmphasizeTitlesConditionForInput(
624     const AutocompleteInput& input) {
625   if (base::FeatureList::IsEnabled(omnibox::kUIExperimentSwapTitleAndUrl)) {
626     return EMPHASIZE_WHEN_NONEMPTY;
627   }
628 
629   // Touch-optimized UI always swaps title and URL.
630   if (ui::TouchUiController::Get()->touch_ui())
631     return EMPHASIZE_WHEN_NONEMPTY;
632 
633   // Look up the parameter named kEmphasizeTitlesRule + "_" + input.type(),
634   // find its value, and return that value as an enum.  If the parameter
635   // isn't redefined, fall back to the generic rule kEmphasizeTitlesRule + "_*"
636   std::string value_str(variations::GetVariationParamValue(
637       kBundledExperimentFieldTrialName,
638       std::string(kEmphasizeTitlesRule) + "_" +
639           base::NumberToString(static_cast<int>(input.type()))));
640   if (value_str.empty()) {
641     value_str = variations::GetVariationParamValue(
642         kBundledExperimentFieldTrialName,
643         std::string(kEmphasizeTitlesRule) + "_*");
644   }
645   if (value_str.empty())
646     return EMPHASIZE_NEVER;
647   // This is a best-effort conversion; we trust the hand-crafted parameters
648   // downloaded from the server to be perfect.  There's no need for handle
649   // errors smartly.
650   int value;
651   base::StringToInt(value_str, &value);
652   return static_cast<EmphasizeTitlesCondition>(value);
653 }
654 
IsShortBookmarkSuggestionsEnabled()655 bool OmniboxFieldTrial::IsShortBookmarkSuggestionsEnabled() {
656   return base::FeatureList::IsEnabled(
657              omnibox::kOmniboxShortBookmarkSuggestions) ||
658          base::FeatureList::IsEnabled(omnibox::kRichAutocompletion);
659 }
660 
IsSuggestionButtonRowEnabled()661 bool OmniboxFieldTrial::IsSuggestionButtonRowEnabled() {
662   return base::FeatureList::IsEnabled(omnibox::kOmniboxSuggestionButtonRow);
663 }
664 
IsTabSwitchSuggestionsEnabled()665 bool OmniboxFieldTrial::IsTabSwitchSuggestionsEnabled() {
666   return base::FeatureList::IsEnabled(omnibox::kOmniboxTabSwitchSuggestions);
667 }
668 
IsPedalSuggestionsEnabled()669 bool OmniboxFieldTrial::IsPedalSuggestionsEnabled() {
670   return base::FeatureList::IsEnabled(omnibox::kOmniboxSuggestionButtonRow) &&
671          base::FeatureList::IsEnabled(omnibox::kOmniboxPedalSuggestions);
672 }
673 
IsKeywordSearchButtonEnabled()674 bool OmniboxFieldTrial::IsKeywordSearchButtonEnabled() {
675   return base::FeatureList::IsEnabled(omnibox::kOmniboxSuggestionButtonRow) &&
676          base::FeatureList::IsEnabled(omnibox::kOmniboxKeywordSearchButton);
677 }
678 
IsExperimentalKeywordModeEnabled()679 bool OmniboxFieldTrial::IsExperimentalKeywordModeEnabled() {
680   return base::FeatureList::IsEnabled(omnibox::kExperimentalKeywordMode);
681 }
682 
IsRefinedFocusStateEnabled()683 bool OmniboxFieldTrial::IsRefinedFocusStateEnabled() {
684   return base::FeatureList::IsEnabled(omnibox::kOmniboxRefinedFocusState);
685 }
686 
IsRichAutocompletionEnabled()687 bool OmniboxFieldTrial::IsRichAutocompletionEnabled() {
688   return base::FeatureList::IsEnabled(omnibox::kRichAutocompletion);
689 }
690 
RichAutocompletionAutocompleteTitles()691 bool OmniboxFieldTrial::RichAutocompletionAutocompleteTitles() {
692   return base::GetFieldTrialParamByFeatureAsBool(
693       omnibox::kRichAutocompletion, kRichAutocompletionAutocompleteTitlesParam,
694       false);
695 }
696 
RichAutocompletionAutocompleteTitlesMinChar()697 size_t OmniboxFieldTrial::RichAutocompletionAutocompleteTitlesMinChar() {
698   return base::GetFieldTrialParamByFeatureAsInt(
699       omnibox::kRichAutocompletion,
700       kRichAutocompletionAutocompleteTitlesMinCharParam, 0);
701 }
702 
RichAutocompletionTwoLineOmnibox()703 bool OmniboxFieldTrial::RichAutocompletionTwoLineOmnibox() {
704   return base::GetFieldTrialParamByFeatureAsBool(
705       omnibox::kRichAutocompletion, kRichAutocompletionTwoLineOmniboxParam,
706       false);
707 }
708 
RichAutocompletionShowTitles()709 bool OmniboxFieldTrial::RichAutocompletionShowTitles() {
710   return base::GetFieldTrialParamByFeatureAsBool(
711       omnibox::kRichAutocompletion, kRichAutocompletionShowTitlesParam, false);
712 }
713 
RichAutocompletionAutocompleteNonPrefixAll()714 bool OmniboxFieldTrial::RichAutocompletionAutocompleteNonPrefixAll() {
715   return base::GetFieldTrialParamByFeatureAsBool(
716       omnibox::kRichAutocompletion,
717       kRichAutocompletionAutocompleteNonPrefixAllParam, false);
718 }
719 
720 bool OmniboxFieldTrial::
RichAutocompletionAutocompleteNonPrefixShortcutProvider()721     RichAutocompletionAutocompleteNonPrefixShortcutProvider() {
722   return base::GetFieldTrialParamByFeatureAsBool(
723       omnibox::kRichAutocompletion,
724       kRichAutocompletionAutocompleteNonPrefixShortcutProviderParam, false);
725 }
726 
RichAutocompletionAutocompleteNonPrefixMinChar()727 size_t OmniboxFieldTrial::RichAutocompletionAutocompleteNonPrefixMinChar() {
728   return base::GetFieldTrialParamByFeatureAsInt(
729       omnibox::kRichAutocompletion,
730       kRichAutocompletionAutocompleteNonPrefixMinCharParam, 0);
731 }
732 
RichAutocompletionShowAdditionalText()733 bool OmniboxFieldTrial::RichAutocompletionShowAdditionalText() {
734   return OmniboxFieldTrial::IsRichAutocompletionEnabled() &&
735          base::GetFieldTrialParamByFeatureAsBool(
736              omnibox::kRichAutocompletion,
737              kRichAutocompletionShowAdditionalTextParam, true);
738 }
739 
RichAutocompletionSplitTitleCompletion()740 bool OmniboxFieldTrial::RichAutocompletionSplitTitleCompletion() {
741   return OmniboxFieldTrial::IsRichAutocompletionEnabled() &&
742          base::GetFieldTrialParamByFeatureAsBool(
743              omnibox::kRichAutocompletion,
744              kRichAutocompletionSplitTitleCompletionParam, false);
745 }
746 
RichAutocompletionSplitUrlCompletion()747 bool OmniboxFieldTrial::RichAutocompletionSplitUrlCompletion() {
748   return OmniboxFieldTrial::IsRichAutocompletionEnabled() &&
749          base::GetFieldTrialParamByFeatureAsBool(
750              omnibox::kRichAutocompletion,
751              kRichAutocompletionSplitUrlCompletionParam, false);
752 }
753 
RichAutocompletionSplitCompletionMinChar()754 size_t OmniboxFieldTrial::RichAutocompletionSplitCompletionMinChar() {
755   return base::GetFieldTrialParamByFeatureAsInt(
756       omnibox::kRichAutocompletion,
757       kRichAutocompletionSplitCompletionMinCharParam, 0);
758 }
759 
IsOnDeviceHeadSuggestEnabledForIncognito()760 bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForIncognito() {
761   return base::FeatureList::IsEnabled(omnibox::kOnDeviceHeadProviderIncognito);
762 }
763 
IsOnDeviceHeadSuggestEnabledForNonIncognito()764 bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForNonIncognito() {
765   return base::FeatureList::IsEnabled(
766       omnibox::kOnDeviceHeadProviderNonIncognito);
767 }
768 
IsOnDeviceHeadSuggestEnabledForAnyMode()769 bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForAnyMode() {
770   return IsOnDeviceHeadSuggestEnabledForIncognito() ||
771          IsOnDeviceHeadSuggestEnabledForNonIncognito();
772 }
773 
OnDeviceHeadModelLocaleConstraint(bool is_incognito)774 std::string OmniboxFieldTrial::OnDeviceHeadModelLocaleConstraint(
775     bool is_incognito) {
776   const base::Feature* feature =
777       is_incognito ? &omnibox::kOnDeviceHeadProviderIncognito
778                    : &omnibox::kOnDeviceHeadProviderNonIncognito;
779   return base::GetFieldTrialParamValueByFeature(
780       *feature, kOnDeviceHeadModelLocaleConstraint);
781 }
782 
OnDeviceHeadSuggestMaxScoreForNonUrlInput(bool is_incognito,const int default_score)783 int OmniboxFieldTrial::OnDeviceHeadSuggestMaxScoreForNonUrlInput(
784     bool is_incognito,
785     const int default_score) {
786   return is_incognito
787              ? default_score
788              : base::GetFieldTrialParamByFeatureAsInt(
789                    omnibox::kOnDeviceHeadProviderNonIncognito,
790                    kOnDeviceHeadSuggestMaxScoreForNonUrlInput, default_score);
791 }
792 
OnDeviceHeadSuggestDelaySuggestRequestMs(bool is_incognito)793 int OmniboxFieldTrial::OnDeviceHeadSuggestDelaySuggestRequestMs(
794     bool is_incognito) {
795   const int kDefaultDelayNonIncognito =
796 #if defined(OS_ANDROID) || defined(OS_IOS)
797       100;
798 #else
799       0;
800 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
801   return is_incognito ? 0
802                       : base::GetFieldTrialParamByFeatureAsInt(
803                             omnibox::kOnDeviceHeadProviderNonIncognito,
804                             kOnDeviceHeadSuggestDelaySuggestRequestMs,
805                             kDefaultDelayNonIncognito);
806 }
807 
OnDeviceSearchProviderDefaultLoaderTimeoutMs(bool is_incognito)808 int OmniboxFieldTrial::OnDeviceSearchProviderDefaultLoaderTimeoutMs(
809     bool is_incognito) {
810   return is_incognito ? 0
811                       : base::GetFieldTrialParamByFeatureAsInt(
812                             omnibox::kOnDeviceHeadProviderNonIncognito,
813                             kOnDeviceSearchProviderDefaultLoaderTimeoutMs, 0);
814 }
815 
OnDeviceHeadSuggestDemoteMode()816 std::string OmniboxFieldTrial::OnDeviceHeadSuggestDemoteMode() {
817   return base::GetFieldTrialParamValueByFeature(
818       omnibox::kOnDeviceHeadProviderNonIncognito,
819       kOnDeviceHeadSuggestDemoteMode);
820 }
821 
ShouldRevealPathQueryRefOnHover()822 bool OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover() {
823   return base::FeatureList::IsEnabled(
824       omnibox::kRevealSteadyStateUrlPathQueryAndRefOnHover);
825 }
826 
ShouldHidePathQueryRefOnInteraction()827 bool OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() {
828   return base::FeatureList::IsEnabled(
829       omnibox::kHideSteadyStateUrlPathQueryAndRefOnInteraction);
830 }
831 
ShouldMaybeElideToRegistrableDomain()832 bool OmniboxFieldTrial::ShouldMaybeElideToRegistrableDomain() {
833   return base::FeatureList::IsEnabled(omnibox::kMaybeElideToRegistrableDomain);
834 }
835 
UnelideURLOnHoverThresholdMs()836 int OmniboxFieldTrial::UnelideURLOnHoverThresholdMs() {
837   const int kDefaultThresholdMs = 250;
838   int threshold = base::GetFieldTrialParamByFeatureAsInt(
839       omnibox::kRevealSteadyStateUrlPathQueryAndRefOnHover,
840       kOmniboxUIUnelideURLOnHoverThresholdMsParam, kDefaultThresholdMs);
841   return threshold < 0 ? kDefaultThresholdMs : threshold;
842 }
843 
844 const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] =
845     "OmniboxBundledExperimentV1";
846 const char OmniboxFieldTrial::kDisableProvidersRule[] = "DisableProviders";
847 const char OmniboxFieldTrial::kShortcutsScoringMaxRelevanceRule[] =
848     "ShortcutsScoringMaxRelevance";
849 const char OmniboxFieldTrial::kSearchHistoryRule[] = "SearchHistory";
850 const char OmniboxFieldTrial::kDemoteByTypeRule[] = "DemoteByType";
851 const char OmniboxFieldTrial::kHQPBookmarkValueRule[] = "HQPBookmarkValue";
852 const char OmniboxFieldTrial::kHQPTypedValueRule[] = "HQPTypedValue";
853 const char OmniboxFieldTrial::kHQPAllowMatchInTLDRule[] = "HQPAllowMatchInTLD";
854 const char OmniboxFieldTrial::kHQPAllowMatchInSchemeRule[] =
855     "HQPAllowMatchInScheme";
856 const char
857     OmniboxFieldTrial::kMeasureSuggestPollingDelayFromLastKeystrokeRule[] =
858         "MeasureSuggestPollingDelayFromLastKeystroke";
859 const char OmniboxFieldTrial::kSuggestPollingDelayMsRule[] =
860     "SuggestPollingDelayMs";
861 const char OmniboxFieldTrial::kHQPMaxVisitsToScoreRule[] =
862     "HQPMaxVisitsToScoreRule";
863 const char OmniboxFieldTrial::kHQPNumMatchesScoresRule[] =
864     "HQPNumMatchesScores";
865 const char OmniboxFieldTrial::kHQPNumTitleWordsRule[] = "HQPNumTitleWords";
866 const char OmniboxFieldTrial::kHQPAlsoDoHUPLikeScoringRule[] =
867     "HQPAlsoDoHUPLikeScoring";
868 const char OmniboxFieldTrial::kHUPSearchDatabaseRule[] = "HUPSearchDatabase";
869 const char OmniboxFieldTrial::kKeywordRequiresRegistryRule[] =
870     "KeywordRequiresRegistry";
871 const char OmniboxFieldTrial::kKeywordScoreForSufficientlyCompleteMatchRule[] =
872     "KeywordScoreForSufficientlyCompleteMatch";
873 const char OmniboxFieldTrial::kEmphasizeTitlesRule[] = "EmphasizeTitles";
874 
875 const char OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam[] =
876     "TypedCountRelevanceCap";
877 const char OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam[] =
878     "TypedCountHalfLifeTime";
879 const char OmniboxFieldTrial::kHUPNewScoringTypedCountScoreBucketsParam[] =
880     "TypedCountScoreBuckets";
881 const char OmniboxFieldTrial::kHUPNewScoringTypedCountUseDecayFactorParam[] =
882     "TypedCountUseDecayFactor";
883 const char OmniboxFieldTrial::kHUPNewScoringVisitedCountRelevanceCapParam[] =
884     "VisitedCountRelevanceCap";
885 const char OmniboxFieldTrial::kHUPNewScoringVisitedCountHalfLifeTimeParam[] =
886     "VisitedCountHalfLifeTime";
887 const char OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam[] =
888     "VisitedCountScoreBuckets";
889 const char OmniboxFieldTrial::kHUPNewScoringVisitedCountUseDecayFactorParam[] =
890     "VisitedCountUseDecayFactor";
891 
892 const char OmniboxFieldTrial::kHQPExperimentalScoringBucketsParam[] =
893     "HQPExperimentalScoringBuckets";
894 const char
895     OmniboxFieldTrial::kHQPExperimentalScoringTopicalityThresholdParam[] =
896         "HQPExperimentalScoringTopicalityThreshold";
897 
898 const char
899     OmniboxFieldTrial::kMaxNumHQPUrlsIndexedAtStartupOnLowEndDevicesParam[] =
900         "MaxNumHQPUrlsIndexedAtStartupOnLowEndDevices";
901 const char
902     OmniboxFieldTrial::kMaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevicesParam[] =
903         "MaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevices";
904 
905 const char OmniboxFieldTrial::kOmniboxLocalZeroSuggestAgeThresholdParam[] =
906     "OmniboxLocalZeroSuggestAgeThreshold";
907 
908 const char OmniboxFieldTrial::kMaxZeroSuggestMatchesParam[] =
909     "MaxZeroSuggestMatches";
910 const char OmniboxFieldTrial::kOmniboxMaxURLMatchesParam[] =
911     "OmniboxMaxURLMatches";
912 const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesByProviderParam[] =
913     "UIMaxAutocompleteMatchesByProvider";
914 const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam[] =
915     "UIMaxAutocompleteMatches";
916 const char OmniboxFieldTrial::kDynamicMaxAutocompleteUrlCutoffParam[] =
917     "OmniboxDynamicMaxAutocompleteUrlCutoff";
918 const char OmniboxFieldTrial::kDynamicMaxAutocompleteIncreasedLimitParam[] =
919     "OmniboxDynamicMaxAutocompleteIncreasedLimit";
920 
921 const char OmniboxFieldTrial::kBubbleUrlSuggestionsAbsoluteGapParam[] =
922     "OmniboxBubbleUrlSuggestionsAbsoluteGap";
923 const char OmniboxFieldTrial::kBubbleUrlSuggestionsRelativeGapParam[] =
924     "OmniboxBubbleUrlSuggestionsRelativeGap";
925 const char OmniboxFieldTrial::kBubbleUrlSuggestionsAbsoluteBufferParam[] =
926     "OmniboxBubbleUrlSuggestionsAbsoluteBuffer";
927 const char OmniboxFieldTrial::kBubbleUrlSuggestionsRelativeBufferParam[] =
928     "OmniboxBubbleUrlSuggestionsRelativeBuffer";
929 
930 const char OmniboxFieldTrial::kOnDeviceHeadModelLocaleConstraint[] =
931     "ForceModelLocaleConstraint";
932 const char OmniboxFieldTrial::kOnDeviceHeadSuggestMaxScoreForNonUrlInput[] =
933     "OnDeviceSuggestMaxScoreForNonUrlInput";
934 const char OmniboxFieldTrial::kOnDeviceHeadSuggestDelaySuggestRequestMs[] =
935     "DelayOnDeviceHeadSuggestRequestMs";
936 const char OmniboxFieldTrial::kOnDeviceSearchProviderDefaultLoaderTimeoutMs[] =
937     "SearchProviderDefaultLoaderTimeoutMs";
938 const char OmniboxFieldTrial::kOnDeviceHeadSuggestDemoteMode[] =
939     "DemoteOnDeviceSearchSuggestionsMode";
940 
941 int OmniboxFieldTrial::kDefaultMinimumTimeBetweenSuggestQueriesMs = 100;
942 
943 const char OmniboxFieldTrial::kRichAutocompletionAutocompleteTitlesParam[] =
944     "RichAutocompletionAutocompleteTitles";
945 const char
946     OmniboxFieldTrial::kRichAutocompletionAutocompleteTitlesMinCharParam[] =
947         "RichAutocompletionAutocompleteTitlesMinChar";
948 const char OmniboxFieldTrial::kRichAutocompletionTwoLineOmniboxParam[] =
949     "RichAutocompletionTwoLineOmnibox";
950 const char OmniboxFieldTrial::kRichAutocompletionShowTitlesParam[] =
951     "RichAutocompletionShowTitles";
952 const char
953     OmniboxFieldTrial::kRichAutocompletionAutocompleteNonPrefixAllParam[] =
954         "RichAutocompletionAutocompleteNonPrefixAll";
955 const char OmniboxFieldTrial::
956     kRichAutocompletionAutocompleteNonPrefixShortcutProviderParam[] =
957         "RichAutocompletionAutocompleteNonPrefixShortcutProvider";
958 const char
959     OmniboxFieldTrial::kRichAutocompletionAutocompleteNonPrefixMinCharParam[] =
960         "RichAutocompletionAutocompleteNonPrefixMinChar";
961 const char OmniboxFieldTrial::kRichAutocompletionShowAdditionalTextParam[] =
962     "RichAutocompletionAutocompleteShowAdditionalText";
963 const char OmniboxFieldTrial::kRichAutocompletionSplitTitleCompletionParam[] =
964     "RichAutocompletionSplitTitleCompletion";
965 const char OmniboxFieldTrial::kRichAutocompletionSplitUrlCompletionParam[] =
966     "RichAutocompletionSplitUrlCompletion";
967 const char OmniboxFieldTrial::kRichAutocompletionSplitCompletionMinCharParam[] =
968     "RichAutocompletionSplitCompletionMinChar";
969 
970 const char OmniboxFieldTrial::kOmniboxUIUnelideURLOnHoverThresholdMsParam[] =
971     "OmniboxUIUnelideURLOnHoverThresholdMsdMs";
972 
973 const char
974     OmniboxFieldTrial::kEntitySuggestionsReduceLatencyDecoderTimeoutParam[] =
975         "EntitySuggestionsReduceLatencyDecoderTimeout";
976 const char
977     OmniboxFieldTrial::kEntitySuggestionsReduceLatencyDecoderWakeupParam[] =
978         "EntitySuggestionsReduceLatencyDecoderWakeup";
979 
980 extern const char OmniboxFieldTrial::kBookmarkPathsUiReplaceTitle[] =
981     "OmniboxBookmarkPathsUiReplaceTitle";
982 extern const char OmniboxFieldTrial::kBookmarkPathsUiReplaceUrl[] =
983     "OmniboxBookmarkPathsUiReplaceUrl";
984 extern const char OmniboxFieldTrial::kBookmarkPathsUiAppendAfterTitle[] =
985     "OmniboxBookmarkPathsUiAppendAfterTitle";
986 extern const char OmniboxFieldTrial::kBookmarkPathsUiDynamicReplaceUrl[] =
987     "OmniboxBookmarkPathsUiDynamicReplaceUrl";
988 
GetValueForRuleInContext(const std::string & rule,OmniboxEventProto::PageClassification page_classification)989 std::string OmniboxFieldTrial::internal::GetValueForRuleInContext(
990     const std::string& rule,
991     OmniboxEventProto::PageClassification page_classification) {
992   VariationParams params;
993   if (!base::GetFieldTrialParams(kBundledExperimentFieldTrialName, &params))
994     return std::string();
995 
996   return GetValueForRuleInContextFromVariationParams(params, rule,
997                                                      page_classification);
998 }
999 
GetValueForRuleInContextByFeature(const base::Feature & feature,const std::string & rule,metrics::OmniboxEventProto::PageClassification page_classification)1000 std::string OmniboxFieldTrial::internal::GetValueForRuleInContextByFeature(
1001     const base::Feature& feature,
1002     const std::string& rule,
1003     metrics::OmniboxEventProto::PageClassification page_classification) {
1004   VariationParams params;
1005   if (!base::GetFieldTrialParamsByFeature(feature, &params))
1006     return std::string();
1007 
1008   return GetValueForRuleInContextFromVariationParams(params, rule,
1009                                                      page_classification);
1010 }
1011