blob: 417e44ca718ab8df7b790695e7fac69a025edddc [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/omnibox/browser/omnibox_field_trial.h"
#include <algorithm>
#include <cmath>
#include <functional>
#include <string>
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "build/build_config.h"
#include "components/history/core/browser/url_database.h"
#include "components/omnibox/browser/url_index_private_data.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/optimization_guide/machine_learning_tflite_buildflags.h"
#include "components/search/search.h"
#include "components/variations/active_field_trials.h"
#include "components/variations/hashing.h"
#include "components/variations/variations_associated_data.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
#include "ui/base/ui_base_features.h"
using metrics::OmniboxEventProto;
namespace {
typedef std::map<std::string, std::string> VariationParams;
typedef HUPScoringParams::ScoreBuckets ScoreBuckets;
void InitializeBucketsFromString(const std::string& bucket_string,
ScoreBuckets* score_buckets) {
// Clear the buckets.
score_buckets->buckets().clear();
base::StringPairs kv_pairs;
if (base::SplitStringIntoKeyValuePairs(bucket_string, ':', ',', &kv_pairs)) {
for (base::StringPairs::const_iterator it = kv_pairs.begin();
it != kv_pairs.end(); ++it) {
ScoreBuckets::CountMaxRelevance bucket;
base::StringToDouble(it->first, &bucket.first);
base::StringToInt(it->second, &bucket.second);
score_buckets->buckets().push_back(bucket);
}
std::sort(score_buckets->buckets().begin(), score_buckets->buckets().end(),
std::greater<ScoreBuckets::CountMaxRelevance>());
}
}
void 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) {
auto it = params.find(relevance_cap_param);
if (it != params.end()) {
int relevance_cap;
if (base::StringToInt(it->second, &relevance_cap)) {
score_buckets->set_relevance_cap(relevance_cap);
}
}
it = params.find(use_decay_factor_param);
if (it != params.end()) {
int use_decay_factor;
if (base::StringToInt(it->second, &use_decay_factor)) {
score_buckets->set_use_decay_factor(use_decay_factor != 0);
}
}
it = params.find(half_life_param);
if (it != params.end()) {
int half_life_days;
if (base::StringToInt(it->second, &half_life_days)) {
score_buckets->set_half_life_days(half_life_days);
}
}
it = params.find(score_buckets_param);
if (it != params.end()) {
// The value of the score bucket is a comma-separated list of
// {DecayedCount/DecayedFactor + ":" + MaxRelevance}.
InitializeBucketsFromString(it->second, score_buckets);
}
}
// Background and implementation details:
//
// Each experiment group in any field trial can come with an optional set of
// parameters (key-value pairs). In the bundled omnibox experiment
// (kBundledExperimentFieldTrialName), each experiment group comes with a
// list of parameters in the form:
// key=<Rule>:
// <OmniboxEventProto::PageClassification (as an int)>:
// <whether Instant Extended is enabled (as a 1 or 0)>
// (note that there are no linebreaks in keys; this format is for
// presentation only>
// value=<arbitrary string>
// Both the OmniboxEventProto::PageClassification and the Instant Extended
// entries can be "*", which means this rule applies for all values of the
// matching portion of the context.
// One example parameter is
// key=SearchHistory:6:1
// value=PreventInlining
// This means in page classification context 6 (a search result page doing
// search term replacement) with Instant Extended enabled, the SearchHistory
// experiment should PreventInlining.
//
// When an exact match to the rule in the current context is missing, we
// give preference to a wildcard rule that matches the instant extended
// context over a wildcard rule that matches the page classification
// context. Hopefully, though, users will write their field trial configs
// so as not to rely on this fall back order.
//
// In short, this function tries to find the value associated with key
// |rule|:|page_classification|:|instant_extended|, failing that it looks up
// |rule|:*:|instant_extended|, failing that it looks up
// |rule|:|page_classification|:*, failing that it looks up |rule|:*:*,
// and failing that it returns the empty string.
std::string GetValueForRuleInContextFromVariationParams(
const std::map<std::string, std::string>& params,
const std::string& rule,
OmniboxEventProto::PageClassification page_classification) {
if (params.empty()) {
return std::string();
}
const std::string page_classification_str =
base::NumberToString(static_cast<int>(page_classification));
const std::string instant_extended =
search::IsInstantExtendedAPIEnabled() ? "1" : "0";
// Look up rule in this exact context.
VariationParams::const_iterator it = params.find(
rule + ":" + page_classification_str + ":" + instant_extended);
if (it != params.end()) {
return it->second;
}
// Fall back to the global page classification context.
it = params.find(rule + ":*:" + instant_extended);
if (it != params.end()) {
return it->second;
}
// Fall back to the global instant extended context.
it = params.find(rule + ":" + page_classification_str + ":*");
if (it != params.end()) {
return it->second;
}
// Look up rule in the global context.
it = params.find(rule + ":*:*");
return (it != params.end()) ? it->second : std::string();
}
OmniboxFieldTrial::MLConfig& GetMLConfigInternal() {
static OmniboxFieldTrial::MLConfig s_config;
return s_config;
}
} // namespace
HUPScoringParams::ScoreBuckets::ScoreBuckets()
: relevance_cap_(-1), half_life_days_(-1), use_decay_factor_(false) {}
HUPScoringParams::ScoreBuckets::ScoreBuckets(const ScoreBuckets& other) =
default;
HUPScoringParams::ScoreBuckets::~ScoreBuckets() {}
size_t HUPScoringParams::ScoreBuckets::EstimateMemoryUsage() const {
return base::trace_event::EstimateMemoryUsage(buckets_);
}
double HUPScoringParams::ScoreBuckets::HalfLifeTimeDecay(
const base::TimeDelta& elapsed_time) const {
double time_ms;
if ((half_life_days_ <= 0) ||
((time_ms = elapsed_time.InMillisecondsF()) <= 0)) {
return 1.0;
}
const double half_life_intervals =
time_ms / base::Days(half_life_days_).InMillisecondsF();
return pow(2.0, -half_life_intervals);
}
size_t HUPScoringParams::EstimateMemoryUsage() const {
size_t res = 0;
res += base::trace_event::EstimateMemoryUsage(typed_count_buckets);
res += base::trace_event::EstimateMemoryUsage(visited_count_buckets);
return res;
}
int OmniboxFieldTrial::GetDisabledProviderTypes() {
const std::string& types_string = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName, kDisableProvidersRule);
int types = 0;
if (types_string.empty() || !base::StringToInt(types_string, &types)) {
return 0;
}
return types;
}
void OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(
std::vector<uint32_t>* field_trial_hashes) {
field_trial_hashes->clear();
if (base::FieldTrialList::TrialExists(kBundledExperimentFieldTrialName)) {
field_trial_hashes->push_back(
variations::HashName(kBundledExperimentFieldTrialName));
}
}
void OmniboxFieldTrial::GetDemotionsByType(
OmniboxEventProto::PageClassification current_page_classification,
DemotionMultipliers* demotions_by_type) {
demotions_by_type->clear();
// Explicitly check whether the feature is enabled before calling
// |GetValueForRuleInContextByFeature| because it is possible for
// |GetValueForRuleInContextByFeature| to return an empty string even if the
// feature is enabled, and we don't want to fallback to
// |GetValueForRuleInContext| in this case.
std::string demotion_rule =
base::FeatureList::IsEnabled(omnibox::kOmniboxDemoteByType)
? OmniboxFieldTrial::internal::GetValueForRuleInContextByFeature(
omnibox::kOmniboxDemoteByType, kDemoteByTypeRule,
current_page_classification)
: OmniboxFieldTrial::internal::GetValueForRuleInContext(
kDemoteByTypeRule, current_page_classification);
// If there is no demotion rule for this context, then use the default
// value for that context.
if (demotion_rule.empty()) {
// This rule demotes URLs as strongly as possible without violating user
// expectations. In particular, for URL-seeking inputs, if the user would
// likely expect a URL first (i.e., it would be inline autocompleted), then
// that URL will still score strongly enough to be first. This is done
// using a demotion multipler of 0.61. If a URL would get a score high
// enough to be inline autocompleted (1400+), even after demotion it will
// score above 850 ( 1400 * 0.61 > 850). 850 is the maximum score for
// queries when the input has been detected as URL-seeking.
#if BUILDFLAG(IS_ANDROID)
if (current_page_classification ==
OmniboxEventProto::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT) {
demotion_rule = "1:61,2:61,3:61,4:61,16:61,24:61";
}
#endif
if (current_page_classification ==
OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS ||
current_page_classification == OmniboxEventProto::NTP_REALBOX) {
demotion_rule = "1:10,2:10,3:10,4:10,5:10,16:10,17:10,24:10";
}
}
// The value of the DemoteByType rule is a comma-separated list of
// {ResultType + ":" + Number} where ResultType is an AutocompleteMatchType::
// Type enum represented as an integer and Number is an integer number
// between 0 and 100 inclusive. Relevance scores of matches of that result
// type are multiplied by Number / 100. 100 means no change.
base::StringPairs kv_pairs;
if (base::SplitStringIntoKeyValuePairs(demotion_rule, ':', ',', &kv_pairs)) {
for (base::StringPairs::const_iterator it = kv_pairs.begin();
it != kv_pairs.end(); ++it) {
// This is a best-effort conversion; we trust the hand-crafted parameters
// downloaded from the server to be perfect. There's no need to handle
// errors smartly.
int k, v;
base::StringToInt(it->first, &k);
base::StringToInt(it->second, &v);
(*demotions_by_type)[static_cast<AutocompleteMatchType::Type>(k)] =
static_cast<float>(v) / 100.0f;
}
}
}
size_t OmniboxFieldTrial::GetProviderMaxMatches(
AutocompleteProvider::Type provider) {
size_t default_max_matches_per_provider = 3;
std::string param_value = base::GetFieldTrialParamValueByFeature(
omnibox::kUIExperimentMaxAutocompleteMatches,
OmniboxFieldTrial::kUIMaxAutocompleteMatchesByProviderParam);
// If the experiment param specifies a max results for |provider|, return the
// specified limit.
// E.g., if param_value = '3:2' and provider = 3, return 2.
// Otherwise, if the experiment param specifies a default value for
// unspecified providers, return the default value.
// E.g., if param_value = '3:3,*:4' and provider = 1, return 4,
// Otherwise, return |default_max_matches_per_provider|.
base::StringPairs kv_pairs;
if (base::SplitStringIntoKeyValuePairs(param_value, ':', ',', &kv_pairs)) {
for (const auto& kv_pair : kv_pairs) {
int k;
base::StringToInt(kv_pair.first, &k);
size_t v;
base::StringToSizeT(kv_pair.second, &v);
if (kv_pair.first == "*") {
default_max_matches_per_provider = v;
} else if (k == provider) {
return v;
}
}
}
return default_max_matches_per_provider;
}
bool OmniboxFieldTrial::IsMaxURLMatchesFeatureEnabled() {
return base::FeatureList::IsEnabled(omnibox::kOmniboxMaxURLMatches);
}
size_t OmniboxFieldTrial::GetMaxURLMatches() {
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
constexpr size_t kDefaultMaxURLMatches = 5;
#else
constexpr size_t kDefaultMaxURLMatches = 7;
#endif
return base::GetFieldTrialParamByFeatureAsInt(
omnibox::kOmniboxMaxURLMatches,
OmniboxFieldTrial::kOmniboxMaxURLMatchesParam, kDefaultMaxURLMatches);
}
void OmniboxFieldTrial::GetDefaultHUPScoringParams(
HUPScoringParams* scoring_params) {
ScoreBuckets* type_score_buckets = &scoring_params->typed_count_buckets;
type_score_buckets->set_half_life_days(30);
type_score_buckets->set_use_decay_factor(false);
// Default typed count buckets based on decayed typed count. The
// values here are based on the results of field trials to determine what
// maximized overall result quality.
const std::string& typed_count_score_buckets_str =
"1.0:1413,0.97:1390,0.93:1360,0.85:1340,0.72:1320,0.50:1250,0.0:1203";
InitializeBucketsFromString(typed_count_score_buckets_str,
type_score_buckets);
ScoreBuckets* visit_score_buckets = &scoring_params->visited_count_buckets;
visit_score_buckets->set_half_life_days(30);
visit_score_buckets->set_use_decay_factor(false);
// Buckets based on visit count. Like the typed count buckets above, the
// values here were chosen based on field trials. Note that when a URL hasn't
// been visited in the last 30 days, we clamp its score to 100, which
// basically demotes it below any other results in the dropdown.
const std::string& visit_count_score_buckets_str = "4.0:790,0.5:590,0.0:100";
InitializeBucketsFromString(visit_count_score_buckets_str,
visit_score_buckets);
}
void OmniboxFieldTrial::GetExperimentalHUPScoringParams(
HUPScoringParams* scoring_params) {
VariationParams params;
if (!base::GetFieldTrialParams(kBundledExperimentFieldTrialName, &params)) {
return;
}
InitializeScoreBuckets(params, kHUPNewScoringTypedCountRelevanceCapParam,
kHUPNewScoringTypedCountHalfLifeTimeParam,
kHUPNewScoringTypedCountScoreBucketsParam,
kHUPNewScoringTypedCountUseDecayFactorParam,
&scoring_params->typed_count_buckets);
InitializeScoreBuckets(params, kHUPNewScoringVisitedCountRelevanceCapParam,
kHUPNewScoringVisitedCountHalfLifeTimeParam,
kHUPNewScoringVisitedCountScoreBucketsParam,
kHUPNewScoringVisitedCountUseDecayFactorParam,
&scoring_params->visited_count_buckets);
}
float OmniboxFieldTrial::HQPBookmarkValue() {
std::string bookmark_value_str = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName, kHQPBookmarkValueRule);
if (bookmark_value_str.empty()) {
return 10;
}
// This is a best-effort conversion; we trust the hand-crafted parameters
// downloaded from the server to be perfect. There's no need for handle
// errors smartly.
double bookmark_value;
base::StringToDouble(bookmark_value_str, &bookmark_value);
return bookmark_value;
}
bool OmniboxFieldTrial::HQPAllowMatchInTLDValue() {
return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
kHQPAllowMatchInTLDRule) == "true";
}
bool OmniboxFieldTrial::HQPAllowMatchInSchemeValue() {
return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
kHQPAllowMatchInSchemeRule) == "true";
}
void OmniboxFieldTrial::GetSuggestPollingStrategy(bool* from_last_keystroke,
int* polling_delay_ms) {
*from_last_keystroke =
base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName,
kMeasureSuggestPollingDelayFromLastKeystrokeRule) == "true";
const std::string& polling_delay_string = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName, kSuggestPollingDelayMsRule);
if (polling_delay_string.empty() ||
!base::StringToInt(polling_delay_string, polling_delay_ms) ||
(*polling_delay_ms <= 0)) {
*polling_delay_ms = kDefaultMinimumTimeBetweenSuggestQueriesMs;
}
}
std::string OmniboxFieldTrial::HQPExperimentalScoringBuckets() {
return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
kHQPExperimentalScoringBucketsParam);
}
float OmniboxFieldTrial::HQPExperimentalTopicalityThreshold() {
std::string topicality_threshold_str = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName,
kHQPExperimentalScoringTopicalityThresholdParam);
double topicality_threshold;
if (topicality_threshold_str.empty() ||
!base::StringToDouble(topicality_threshold_str, &topicality_threshold)) {
return 0.5f;
}
return static_cast<float>(topicality_threshold);
}
int OmniboxFieldTrial::MaxNumHQPUrlsIndexedAtStartup() {
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
// Limits on Android and iOS are chosen based on experiment results. See
// crbug.com/715852#c18 and crbug.com/1141539#c31.
constexpr int kDefaultOnLowEndDevices = 100;
constexpr int kDefaultOnNonLowEndDevices = 400;
#else
// Use 20,000 entries as a safety cap for users with spammed history,
// such as users who were stuck in a redirect loop with autogenerated URLs.
// This limit will only affect 0.01% of Windows users. crbug.com/750845.
constexpr int kDefaultOnLowEndDevices = 20000;
constexpr int kDefaultOnNonLowEndDevices = 20000;
#endif
if (base::SysInfo::IsLowEndDeviceOrPartialLowEndModeEnabled()) {
return kDefaultOnLowEndDevices;
} else {
return kDefaultOnNonLowEndDevices;
}
}
size_t OmniboxFieldTrial::HQPMaxVisitsToScore() {
std::string max_visits_str = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName, kHQPMaxVisitsToScoreRule);
constexpr size_t kDefaultMaxVisitsToScore = 10;
static_assert(
URLIndexPrivateData::kMaxVisitsToStoreInCache >= kDefaultMaxVisitsToScore,
"HQP should store at least as many visits as it expects to score");
if (max_visits_str.empty()) {
return kDefaultMaxVisitsToScore;
}
// This is a best-effort conversion; we trust the hand-crafted parameters
// downloaded from the server to be perfect. There's no need for handle
// errors smartly.
size_t max_visits_value;
base::StringToSizeT(max_visits_str, &max_visits_value);
return max_visits_value;
}
float OmniboxFieldTrial::HQPTypedValue() {
std::string typed_value_str = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName, kHQPTypedValueRule);
if (typed_value_str.empty()) {
return 1.5;
}
// This is a best-effort conversion; we trust the hand-crafted parameters
// downloaded from the server to be perfect. There's no need for handle
// errors smartly.
double typed_value;
base::StringToDouble(typed_value_str, &typed_value);
return typed_value;
}
OmniboxFieldTrial::NumMatchesScores OmniboxFieldTrial::HQPNumMatchesScores() {
std::string str = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName, kHQPNumMatchesScoresRule);
static constexpr char kDefaultNumMatchesScores[] = "1:3,2:2.5,3:2,4:1.5";
if (str.empty()) {
str = kDefaultNumMatchesScores;
}
// The parameter is a comma-separated list of (number, value) pairs such as
// listed above.
// This is a best-effort conversion; we trust the hand-crafted parameters
// downloaded from the server to be perfect. There's no need to handle
// errors smartly.
base::StringPairs kv_pairs;
if (!base::SplitStringIntoKeyValuePairs(str, ':', ',', &kv_pairs)) {
return NumMatchesScores{};
}
NumMatchesScores num_matches_scores(kv_pairs.size());
for (size_t i = 0; i < kv_pairs.size(); ++i) {
base::StringToSizeT(kv_pairs[i].first, &num_matches_scores[i].first);
// The input must be sorted by number of matches.
DCHECK((i == 0) ||
(num_matches_scores[i].first > num_matches_scores[i - 1].first));
base::StringToDouble(kv_pairs[i].second, &num_matches_scores[i].second);
}
return num_matches_scores;
}
size_t OmniboxFieldTrial::HQPNumTitleWordsToAllow() {
// The value of the rule is a string that encodes an integer (actually
// size_t) containing the number of words.
size_t num_title_words;
if (!base::StringToSizeT(
base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
kHQPNumTitleWordsRule),
&num_title_words)) {
return 20;
}
return num_title_words;
}
bool OmniboxFieldTrial::HQPAlsoDoHUPLikeScoring() {
return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName,
kHQPAlsoDoHUPLikeScoringRule) == "true";
}
bool OmniboxFieldTrial::HUPSearchDatabase() {
const std::string& value = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName, kHUPSearchDatabaseRule);
return value.empty() || (value == "true");
}
int OmniboxFieldTrial::KeywordScoreForSufficientlyCompleteMatch() {
std::string value_str = base::GetFieldTrialParamValue(
kBundledExperimentFieldTrialName,
kKeywordScoreForSufficientlyCompleteMatchRule);
if (value_str.empty()) {
return -1;
}
// This is a best-effort conversion; we trust the hand-crafted parameters
// downloaded from the server to be perfect. There's no need for handle
// errors smartly.
int value;
base::StringToInt(value_str, &value);
return value;
}
bool OmniboxFieldTrial::IsFuzzyUrlSuggestionsEnabled() {
return base::FeatureList::IsEnabled(omnibox::kOmniboxFuzzyUrlSuggestions);
}
const base::FeatureParam<bool>
OmniboxFieldTrial::kFuzzyUrlSuggestionsCounterfactual(
&omnibox::kOmniboxFuzzyUrlSuggestions,
"FuzzyUrlSuggestionsCounterfactual",
false);
const base::FeatureParam<bool>
OmniboxFieldTrial::kFuzzyUrlSuggestionsLowEndBypass(
&omnibox::kOmniboxFuzzyUrlSuggestions,
"FuzzyUrlSuggestionsLowEndBypass",
false);
const base::FeatureParam<bool> OmniboxFieldTrial::kFuzzyUrlSuggestionsTranspose(
&omnibox::kOmniboxFuzzyUrlSuggestions,
"FuzzyUrlSuggestionsTranspose",
true);
const base::FeatureParam<int>
OmniboxFieldTrial::kFuzzyUrlSuggestionsMinInputLength(
&omnibox::kOmniboxFuzzyUrlSuggestions,
"FuzzyUrlSuggestionsMinInputLength",
3);
// Note about this default, which produces good results for most inputs:
// Using 10% reasonably took a 1334 relevance match down to 1200,
// but was harmful to HQP suggestions: as soon as a '.' was
// appended, a bunch of ~800 navsuggest results overtook a better
// HQP result that was bumped down to ~770. Using 5% lets this
// result compete in the navsuggest range.
const base::FeatureParam<int> OmniboxFieldTrial::kFuzzyUrlSuggestionsPenaltyLow(
&omnibox::kOmniboxFuzzyUrlSuggestions,
"FuzzyUrlSuggestionsPenaltyLow",
5);
// Keeping the default for high penalty equal to preserve current behavior, but
// this is the parameter most likely to need tuning for very short inputs.
const base::FeatureParam<int>
OmniboxFieldTrial::kFuzzyUrlSuggestionsPenaltyHigh(
&omnibox::kOmniboxFuzzyUrlSuggestions,
"FuzzyUrlSuggestionsPenaltyHigh",
5);
// The default value of zero means "no taper", and only the lowest penalty
// will be applied.
const base::FeatureParam<int>
OmniboxFieldTrial::kFuzzyUrlSuggestionsPenaltyTaperLength(
&omnibox::kOmniboxFuzzyUrlSuggestions,
"FuzzyUrlSuggestionsPenaltyTaperLength",
0);
bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForIncognito() {
return base::FeatureList::IsEnabled(omnibox::kOnDeviceHeadProviderIncognito);
}
bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForNonIncognito() {
return base::FeatureList::IsEnabled(
omnibox::kOnDeviceHeadProviderNonIncognito);
}
bool OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForAnyMode() {
return IsOnDeviceHeadSuggestEnabledForIncognito() ||
IsOnDeviceHeadSuggestEnabledForNonIncognito();
}
bool OmniboxFieldTrial::IsOnDeviceTailSuggestEnabled() {
// Tail model will only be enabled when head provider is also enabled.
return base::FeatureList::IsEnabled(omnibox::kOnDeviceTailModel) &&
IsOnDeviceHeadSuggestEnabledForAnyMode();
}
bool OmniboxFieldTrial::ShouldEncodeLeadingSpaceForOnDeviceTailSuggest() {
return base::GetFieldTrialParamByFeatureAsBool(omnibox::kOnDeviceTailModel,
"ShouldEncodeLeadingSpace",
/*default_value=*/false);
}
std::string OmniboxFieldTrial::OnDeviceHeadModelLocaleConstraint(
bool is_incognito) {
const base::Feature* feature =
is_incognito ? &omnibox::kOnDeviceHeadProviderIncognito
: &omnibox::kOnDeviceHeadProviderNonIncognito;
std::string constraint = base::GetFieldTrialParamValueByFeature(
*feature, kOnDeviceHeadModelLocaleConstraint);
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
if (constraint.empty()) {
constraint = "500000";
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
return constraint;
}
bool OmniboxFieldTrial::ShouldDisableCGIParamMatching() {
return base::FeatureList::IsEnabled(omnibox::kDisableCGIParamMatching);
}
bool OmniboxFieldTrial::IsSiteSearchStarterPackEnabled() {
return base::FeatureList::IsEnabled(omnibox::kSiteSearchStarterPack);
}
// Omnibox UI simplification - Uniform Suggestion Row Heights
const base::FeatureParam<bool> OmniboxFieldTrial::kSquareSuggestIconAnswers(
&omnibox::kSquareSuggestIcons,
"OmniboxSquareSuggestIconAnswers",
false);
const base::FeatureParam<bool> OmniboxFieldTrial::kSquareSuggestIconIcons(
&omnibox::kSquareSuggestIcons,
"OmniboxSquareSuggestIconIcons",
false);
const base::FeatureParam<bool> OmniboxFieldTrial::kSquareSuggestIconEntities(
&omnibox::kSquareSuggestIcons,
"OmniboxSquareSuggestIconEntities",
false);
const base::FeatureParam<double>
OmniboxFieldTrial::kSquareSuggestIconEntitiesScale(
&omnibox::kSquareSuggestIcons,
"OmniboxSquareSuggestIconEntitiesScale",
0.8722);
bool OmniboxFieldTrial::IsUniformRowHeightEnabled() {
return base::FeatureList::IsEnabled(omnibox::kUniformRowHeight);
}
const base::FeatureParam<int> OmniboxFieldTrial::kRichSuggestionVerticalMargin(
&omnibox::kUniformRowHeight,
"OmniboxRichSuggestionVerticalMargin",
4);
bool OmniboxFieldTrial::IsChromeRefreshIconsEnabled() {
return features::GetChromeRefresh2023Level() ==
features::ChromeRefresh2023Level::kLevel2 ||
base::FeatureList::IsEnabled(omnibox::kOmniboxCR23SteadyStateIcons);
}
bool OmniboxFieldTrial::IsGM3TextStyleEnabled() {
return features::GetChromeRefresh2023Level() ==
features::ChromeRefresh2023Level::kLevel2 ||
base::FeatureList::IsEnabled(omnibox::kOmniboxSteadyStateTextStyle);
}
// In order to control the value of this "font size" param via Finch, the
// `kOmniboxSteadyStateTextStyle` feature flag must be enabled.
//
// Enabling `ChromeRefresh2023` Level 2 while leaving the
// `kOmniboxSteadyStateTextStyle` flag disabled, will result in the param being
// locked to its default value and ignoring any overrides provided via Finch.
//
// If neither `ChromeRefresh2023` Level 2 nor `kOmniboxSteadyStateTextStyle` are
// enabled, then this "font size" param will have zero effect on Chrome UI.
const base::FeatureParam<int> OmniboxFieldTrial::kFontSizeTouchUI(
&omnibox::kOmniboxSteadyStateTextStyle,
"OmniboxFontSizeTouchUI",
15);
// In order to control the value of this "font size" param via Finch, the
// `kOmniboxSteadyStateTextStyle` feature flag must be enabled.
//
// Enabling `ChromeRefresh2023` Level 2 while leaving the
// `kOmniboxSteadyStateTextStyle` flag disabled, will result in the param being
// locked to its default value and ignoring any overrides provided via Finch.
//
// If neither `ChromeRefresh2023` Level 2 nor `kOmniboxSteadyStateTextStyle` are
// enabled, then this "font size" param will have zero effect on Chrome UI.
const base::FeatureParam<int> OmniboxFieldTrial::kFontSizeNonTouchUI(
&omnibox::kOmniboxSteadyStateTextStyle,
"OmniboxFontSizeNonTouchUI",
12);
const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] =
"OmniboxBundledExperimentV1";
const char OmniboxFieldTrial::kDisableProvidersRule[] = "DisableProviders";
const char OmniboxFieldTrial::kDemoteByTypeRule[] = "DemoteByType";
const char OmniboxFieldTrial::kHQPBookmarkValueRule[] = "HQPBookmarkValue";
const char OmniboxFieldTrial::kHQPTypedValueRule[] = "HQPTypedValue";
const char OmniboxFieldTrial::kHQPAllowMatchInTLDRule[] = "HQPAllowMatchInTLD";
const char OmniboxFieldTrial::kHQPAllowMatchInSchemeRule[] =
"HQPAllowMatchInScheme";
const char
OmniboxFieldTrial::kMeasureSuggestPollingDelayFromLastKeystrokeRule[] =
"MeasureSuggestPollingDelayFromLastKeystroke";
const char OmniboxFieldTrial::kSuggestPollingDelayMsRule[] =
"SuggestPollingDelayMs";
const char OmniboxFieldTrial::kHQPMaxVisitsToScoreRule[] =
"HQPMaxVisitsToScoreRule";
const char OmniboxFieldTrial::kHQPNumMatchesScoresRule[] =
"HQPNumMatchesScores";
const char OmniboxFieldTrial::kHQPNumTitleWordsRule[] = "HQPNumTitleWords";
const char OmniboxFieldTrial::kHQPAlsoDoHUPLikeScoringRule[] =
"HQPAlsoDoHUPLikeScoring";
const char OmniboxFieldTrial::kHUPSearchDatabaseRule[] = "HUPSearchDatabase";
const char OmniboxFieldTrial::kKeywordRequiresRegistryRule[] =
"KeywordRequiresRegistry";
const char OmniboxFieldTrial::kKeywordScoreForSufficientlyCompleteMatchRule[] =
"KeywordScoreForSufficientlyCompleteMatch";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam[] =
"TypedCountRelevanceCap";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam[] =
"TypedCountHalfLifeTime";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountScoreBucketsParam[] =
"TypedCountScoreBuckets";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountUseDecayFactorParam[] =
"TypedCountUseDecayFactor";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountRelevanceCapParam[] =
"VisitedCountRelevanceCap";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountHalfLifeTimeParam[] =
"VisitedCountHalfLifeTime";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam[] =
"VisitedCountScoreBuckets";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountUseDecayFactorParam[] =
"VisitedCountUseDecayFactor";
const char OmniboxFieldTrial::kHQPExperimentalScoringBucketsParam[] =
"HQPExperimentalScoringBuckets";
const char
OmniboxFieldTrial::kHQPExperimentalScoringTopicalityThresholdParam[] =
"HQPExperimentalScoringTopicalityThreshold";
const char
OmniboxFieldTrial::kMaxNumHQPUrlsIndexedAtStartupOnLowEndDevicesParam[] =
"MaxNumHQPUrlsIndexedAtStartupOnLowEndDevices";
const char
OmniboxFieldTrial::kMaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevicesParam[] =
"MaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevices";
const char OmniboxFieldTrial::kMaxZeroSuggestMatchesParam[] =
"MaxZeroSuggestMatches";
const char OmniboxFieldTrial::kOmniboxMaxURLMatchesParam[] =
"OmniboxMaxURLMatches";
const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesByProviderParam[] =
"UIMaxAutocompleteMatchesByProvider";
const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam[] =
"UIMaxAutocompleteMatches";
const char OmniboxFieldTrial::kDynamicMaxAutocompleteUrlCutoffParam[] =
"OmniboxDynamicMaxAutocompleteUrlCutoff";
const char OmniboxFieldTrial::kDynamicMaxAutocompleteIncreasedLimitParam[] =
"OmniboxDynamicMaxAutocompleteIncreasedLimit";
const char OmniboxFieldTrial::kOnDeviceHeadModelLocaleConstraint[] =
"ForceModelLocaleConstraint";
int OmniboxFieldTrial::kDefaultMinimumTimeBetweenSuggestQueriesMs = 100;
namespace OmniboxFieldTrial {
// Autocomplete stability.
const base::FeatureParam<bool>
kAutocompleteStabilityPreserveDefaultExcludeKeywordInputs(
&omnibox::kPreserveDefault,
"AutocompleteStabilityPreserveDefaultExcludeKeywordInputs",
true);
const base::FeatureParam<bool>
kAutocompleteStabilityPreserveDefaultAfterTransfer(
&omnibox::kPreserveDefault,
"AutocompleteStabilityPreserveDefaultAfterTransfer",
true);
const base::FeatureParam<int>
kAutocompleteStabilityPreserveDefaultForSyncUpdatesMinInputLength(
&omnibox::kPreserveDefault,
"AutocompleteStabilityPreserveDefaultForSyncUpdatesMinInputLength",
3);
const base::FeatureParam<bool>
kAutocompleteStabilityPreserveDefaultForAsyncUpdates(
&omnibox::kPreserveDefault,
"AutocompleteStabilityPreserveDefaultForAsyncUpdates",
true);
const base::FeatureParam<bool>
kAutocompleteStabilityPreventDefaultPreviousMatches(
&omnibox::kPreserveDefault,
"AutocompleteStabilityPreventDefaultPreviousMatches",
true);
const base::FeatureParam<bool>
kAutocompleteStabilityUpdateResultDebounceFromLastRun(
&omnibox::kUpdateResultDebounce,
"AutocompleteStabilityUpdateResultDebounceFromLastRun",
false);
const base::FeatureParam<int> kAutocompleteStabilityUpdateResultDebounceDelay(
&omnibox::kUpdateResultDebounce,
"AutocompleteStabilityUpdateResultDebounceDelay",
0);
// Local history zero-prefix (aka zero-suggest) and prefix suggestions:
// The maximum number of entries stored by the in-memory zero-suggest cache at
// at any given time (LRU eviction policy is used to enforce this limit).
const base::FeatureParam<int> kZeroSuggestCacheMaxSize(
&omnibox::kZeroSuggestInMemoryCaching,
"ZeroSuggestCacheMaxSize",
5);
// The relevance score for remote zero-suggest ranges from 550-1400. A default
// value of 500 places local history zero-suggest below the remote zero-suggest.
const base::FeatureParam<int> kLocalHistoryZeroSuggestRelevanceScore(
&omnibox::kAdjustLocalHistoryZeroSuggestRelevanceScore,
"LocalHistoryZeroSuggestRelevanceScore",
500);
bool IsZeroSuggestPrefetchingEnabled() {
return base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetching) ||
base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnSRP) ||
base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnWeb);
}
bool IsZeroSuggestPrefetchingEnabledInContext(
metrics::OmniboxEventProto::PageClassification page_classification) {
switch (page_classification) {
case metrics::OmniboxEventProto::NTP_ZPS_PREFETCH:
return base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetching);
case metrics::OmniboxEventProto::SRP_ZPS_PREFETCH:
return base::FeatureList::IsEnabled(
omnibox::kZeroSuggestPrefetchingOnSRP);
case metrics::OmniboxEventProto::OTHER_ZPS_PREFETCH:
return base::FeatureList::IsEnabled(
omnibox::kZeroSuggestPrefetchingOnWeb);
default:
return false;
}
}
// Short bookmarks.
bool IsShortBookmarkSuggestionsEnabled() {
return base::FeatureList::IsEnabled(omnibox::kShortBookmarkSuggestions);
}
bool IsShortBookmarkSuggestionsByTotalInputLengthEnabled() {
return base::FeatureList::IsEnabled(
omnibox::kShortBookmarkSuggestionsByTotalInputLength) ||
(IsRichAutocompletionEnabled() &&
(kRichAutocompletionAutocompleteTitles.Get() ||
kRichAutocompletionAutocompleteNonPrefixAll.Get()));
}
size_t ShortBookmarkSuggestionsByTotalInputLengthThreshold() {
// The rich autocompletion feature requires this feature to be enabled. If
// short bookmarks is enabled transitively; i.e. rich autocompletion is
// enabled, but short bookmarks isn't explicitly enabled, then use the rich
// autocompletion min char limit.
if (!base::FeatureList::IsEnabled(
omnibox::kShortBookmarkSuggestionsByTotalInputLength) &&
IsRichAutocompletionEnabled()) {
if (kRichAutocompletionAutocompleteTitles.Get() &&
kRichAutocompletionAutocompleteNonPrefixAll.Get()) {
return std::min(kRichAutocompletionAutocompleteTitlesMinChar.Get(),
kRichAutocompletionAutocompleteNonPrefixMinChar.Get());
} else if (kRichAutocompletionAutocompleteTitles.Get()) {
return kRichAutocompletionAutocompleteTitlesMinChar.Get();
} else if (kRichAutocompletionAutocompleteNonPrefixAll.Get()) {
return kRichAutocompletionAutocompleteNonPrefixMinChar.Get();
}
}
return kShortBookmarkSuggestionsByTotalInputLengthThreshold.Get();
}
const base::FeatureParam<bool>
kShortBookmarkSuggestionsByTotalInputLengthCounterfactual(
&omnibox::kShortBookmarkSuggestionsByTotalInputLength,
"ShortBookmarkSuggestionsByTotalInputLengthCounterfactual",
false);
const base::FeatureParam<int>
kShortBookmarkSuggestionsByTotalInputLengthThreshold(
&omnibox::kShortBookmarkSuggestionsByTotalInputLength,
"ShortBookmarkSuggestionsByTotalInputLengthThreshold",
3);
// Shortcut boost
const base::FeatureParam<int> kShortcutBoostSearchScore(
&omnibox::kShortcutBoost,
"ShortcutBoostSearchScore",
0);
const base::FeatureParam<int> kShortcutBoostUrlScore(&omnibox::kShortcutBoost,
"ShortcutBoostUrlScore",
0);
const base::FeatureParam<bool> kShortcutBoostCounterfactual(
&omnibox::kShortcutBoost,
"ShortcutBoostCounterfactual",
false);
// Rich autocompletion.
bool IsRichAutocompletionEnabled() {
return base::FeatureList::IsEnabled(omnibox::kRichAutocompletion);
}
bool RichAutocompletionShowAdditionalText() {
return IsRichAutocompletionEnabled() &&
kRichAutocompletionShowAdditionalText.Get();
}
const base::FeatureParam<bool> kRichAutocompletionAutocompleteTitles(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteTitles",
false);
const base::FeatureParam<bool>
kRichAutocompletionAutocompleteTitlesShortcutProvider(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteTitlesShortcutProvider",
true);
const base::FeatureParam<int> kRichAutocompletionAutocompleteTitlesMinChar(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteTitlesMinChar",
3);
const base::FeatureParam<bool> kRichAutocompletionAutocompleteNonPrefixAll(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteNonPrefixAll",
false);
const base::FeatureParam<bool>
kRichAutocompletionAutocompleteNonPrefixShortcutProvider(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteNonPrefixShortcutProvider",
false);
const base::FeatureParam<int> kRichAutocompletionAutocompleteNonPrefixMinChar(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteNonPrefixMinChar",
0);
const base::FeatureParam<bool> kRichAutocompletionShowAdditionalText(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteShowAdditionalText",
true);
const base::FeatureParam<bool> kRichAutocompletionAdditionalTextWithParenthesis(
&omnibox::kRichAutocompletion,
"RichAutocompletionAdditionalTextWithParenthesis",
false);
const base::FeatureParam<bool> kRichAutocompletionAutocompleteShortcutText(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteShortcutText",
true);
const base::FeatureParam<int>
kRichAutocompletionAutocompleteShortcutTextMinChar(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompleteShortcutTextMinChar",
3);
const base::FeatureParam<bool> kRichAutocompletionCounterfactual(
&omnibox::kRichAutocompletion,
"RichAutocompletionCounterfactual",
false);
const base::FeatureParam<bool>
kRichAutocompletionAutocompletePreferUrlsOverPrefixes(
&omnibox::kRichAutocompletion,
"RichAutocompletionAutocompletePreferUrlsOverPrefixes",
false);
const base::FeatureParam<int> kSiteSearchStarterPackRelevanceScore(
&omnibox::kSiteSearchStarterPack,
"SiteSearchStarterPackRelevanceScore",
1350);
// Rather than have a special default value of -1 to signify no limit, simply
// set it to a large value that'll never be reached in practice.
// TODO(manukh): Launched (set to 1) 3/2/23 m113. Clean up feature code 5/2 when
// m113 reaches stable.
const base::FeatureParam<int> kDocumentProviderMaxLowQualitySuggestions(
&omnibox::kDocumentProvider,
"DocumentProviderMaxLowQualitySuggestions",
1);
const base::FeatureParam<bool> kDomainSuggestionsCounterfactual(
&omnibox::kDomainSuggestions,
"DomainSuggestionsCounterfactual",
false);
const base::FeatureParam<int> kDomainSuggestionsTypedUrlsThreshold(
&omnibox::kDomainSuggestions,
"DomainSuggestionsTypedUrlsThreshold",
7);
const base::FeatureParam<int> kDomainSuggestionsTypedUrlsOffset(
&omnibox::kDomainSuggestions,
"DomainSuggestionsTypedUrlsOffset",
1);
const base::FeatureParam<int> kDomainSuggestionsTypedVisitThreshold(
&omnibox::kDomainSuggestions,
"DomainSuggestionsTypedVisitThreshold",
4);
const base::FeatureParam<int> kDomainSuggestionsTypedVisitOffset(
&omnibox::kDomainSuggestions,
"DomainSuggestionsTypedVisitOffset",
1);
const base::FeatureParam<int> kDomainSuggestionsTypedVisitCapPerVisit(
&omnibox::kDomainSuggestions,
"DomainSuggestionsTypedVisitCapPerVisit",
2);
const base::FeatureParam<int> kDomainSuggestionsMinInputLength(
&omnibox::kDomainSuggestions,
"DomainSuggestionsMinInputLength",
4);
const base::FeatureParam<int> kDomainSuggestionsMaxMatchesPerDomain(
&omnibox::kDomainSuggestions,
"DomainSuggestionsMaxMatchesPerDomain",
2);
const base::FeatureParam<double> kDomainSuggestionsScoreFactor(
&omnibox::kDomainSuggestions,
"DomainSuggestionsScoreFactor",
1);
const base::FeatureParam<bool> kDomainSuggestionsAlternativeScoring(
&omnibox::kDomainSuggestions,
"DomainSuggestionsAlternativeScoring",
false);
// ---------------------------------------------------------
// ML Relevance Scoring ->
// If true, enables scoring signal annotators for logging Omnibox scoring
// signals to OmniboxEventProto.
const base::FeatureParam<bool> kEnableScoringSignalsAnnotators(
&omnibox::kLogUrlScoringSignals,
"enable_scoring_signals_annotators",
false);
// If true, runs the ML scoring model but does not assign new relevance scores
// to the URL suggestions and does not rerank them.
const base::FeatureParam<bool> kMlUrlScoringCounterfactual(
&omnibox::kMlUrlScoring,
"MlUrlScoringCounterfactual",
false);
// If true, increases the number of candidates the URL autocomplete providers
// pass to the controller beyond `provider_max_matches`.
const base::FeatureParam<bool> kMlUrlScoringIncreaseNumCandidates(
&omnibox::kMlUrlScoring,
"MlUrlScoringIncreaseNumCandidates",
false);
MLConfig::MLConfig() {
log_url_scoring_signals =
base::FeatureList::IsEnabled(omnibox::kLogUrlScoringSignals);
enable_scoring_signals_annotators = kEnableScoringSignalsAnnotators.Get();
ml_url_scoring = base::FeatureList::IsEnabled(omnibox::kMlUrlScoring);
ml_url_scoring_counterfactual = kMlUrlScoringCounterfactual.Get();
ml_url_scoring_increase_num_candidates =
kMlUrlScoringIncreaseNumCandidates.Get();
url_scoring_model = base::FeatureList::IsEnabled(omnibox::kUrlScoringModel);
}
ScopedMLConfigForTesting::ScopedMLConfigForTesting()
: original_config_(std::make_unique<MLConfig>(GetMLConfig())) {}
ScopedMLConfigForTesting::~ScopedMLConfigForTesting() {
GetMLConfigInternal() = *original_config_;
}
MLConfig& ScopedMLConfigForTesting::GetMLConfig() {
return GetMLConfigInternal();
}
const MLConfig& GetMLConfig() {
return GetMLConfigInternal();
}
bool IsLogUrlScoringSignalsEnabled() {
return GetMLConfig().log_url_scoring_signals;
}
bool AreScoringSignalsAnnotatorsEnabled() {
return GetMLConfig().enable_scoring_signals_annotators;
}
bool IsMlUrlScoringEnabled() {
#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
return IsUrlScoringModelEnabled() && GetMLConfig().ml_url_scoring;
#else
return false;
#endif // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
}
bool IsMlUrlScoringCounterfactual() {
return IsMlUrlScoringEnabled() && GetMLConfig().ml_url_scoring_counterfactual;
}
bool IsMlUrlScoringIncreaseNumCandidatesEnabled() {
return IsMlUrlScoringEnabled() &&
GetMLConfig().ml_url_scoring_increase_num_candidates;
}
bool IsUrlScoringModelEnabled() {
return GetMLConfig().url_scoring_model;
}
// <- ML Relevance Scoring
// ---------------------------------------------------------
// Two-column realbox ->
const base::FeatureParam<int> kRealboxMaxPreviousSearchRelatedSuggestions(
&omnibox::kRealboxSecondaryZeroSuggest,
"RealboxMaxPreviousSearchRelatedSuggestions",
3);
const base::FeatureParam<bool> kRealboxSecondaryZeroSuggestCounterfactual(
&omnibox::kRealboxSecondaryZeroSuggest,
"RealboxSecondaryZeroSuggestCounterfactual",
false);
// <- Two-column realbox
// ---------------------------------------------------------
// Inspire Me ->
const base::FeatureParam<int> kInspireMeAdditionalRelatedQueries(
&omnibox::kInspireMe,
"AdditionalRelatedQueries",
0);
const base::FeatureParam<int> kInspireMeAdditionalTrendingQueries(
&omnibox::kInspireMe,
"AdditionalTrendingQueries",
0);
// <- Inspire Me
// ---------------------------------------------------------
// Actions In Suggest ->
// When set to true, permits Entity suggestion with associated Actions to be
// promoted over the Escape Hatch.
const base::FeatureParam<bool> kActionsInSuggestPromoteEntitySuggestion(
&omnibox::kActionsInSuggest,
"PromoteEntitySuggestion",
false);
// <- Actions In Suggest
// ---------------------------------------------------------
// Android UI Revamp ->
const base::FeatureParam<bool> kOmniboxModernizeVisualUpdateMergeClipboardOnNTP(
&omnibox::kOmniboxModernizeVisualUpdate,
"modernize_visual_update_merge_clipboard_on_ntp",
false);
// <- Android UI Revamp
// ---------------------------------------------------------
} // namespace OmniboxFieldTrial
std::string OmniboxFieldTrial::internal::GetValueForRuleInContext(
const std::string& rule,
OmniboxEventProto::PageClassification page_classification) {
VariationParams params;
if (!base::GetFieldTrialParams(kBundledExperimentFieldTrialName, &params)) {
return std::string();
}
return GetValueForRuleInContextFromVariationParams(params, rule,
page_classification);
}
std::string OmniboxFieldTrial::internal::GetValueForRuleInContextByFeature(
const base::Feature& feature,
const std::string& rule,
metrics::OmniboxEventProto::PageClassification page_classification) {
VariationParams params;
if (!base::GetFieldTrialParamsByFeature(feature, &params)) {
return std::string();
}
return GetValueForRuleInContextFromVariationParams(params, rule,
page_classification);
}