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, ¶m_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 ¶ms))
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, ¶ms))
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, ¶ms))
1006 return std::string();
1007
1008 return GetValueForRuleInContextFromVariationParams(params, rule,
1009 page_classification);
1010 }
1011