This source file includes following definitions.
- DynamicFieldTrialName
- InitializeScoreBuckets
- half_life_days_
- HalfLifeTimeDecay
- ActivateStaticTrials
- ActivateDynamicTrials
- GetDisabledProviderTypes
- GetActiveSuggestFieldTrialHashes
- InHUPCullRedirectsFieldTrial
- InHUPCullRedirectsFieldTrialExperimentGroup
- InHUPCreateShorterMatchFieldTrial
- InHUPCreateShorterMatchFieldTrialExperimentGroup
- StopTimerFieldTrialDuration
- HasDynamicFieldTrialGroupPrefix
- InZeroSuggestFieldTrial
- InZeroSuggestMostVisitedFieldTrial
- InZeroSuggestAfterTypingFieldTrial
- InZeroSuggestPersonalizedFieldTrial
- ShortcutsScoringMaxRelevance
- SearchHistoryPreventInlining
- SearchHistoryDisable
- GetDemotionsByType
- GetUndemotableTopTypes
- ReorderForLegalDefaultMatch
- GetExperimentalHUPScoringParams
- HQPBookmarkValue
- HQPDiscountFrecencyWhenFewVisits
- HQPAllowMatchInTLDValue
- HQPAllowMatchInSchemeValue
- GetValueForRuleInContext
#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include <cmath>
#include <string>
#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "chrome/browser/autocomplete/autocomplete_input.h"
#include "chrome/browser/search/search.h"
#include "chrome/common/metrics/variations/variation_ids.h"
#include "chrome/common/metrics/variations/variations_util.h"
#include "components/variations/metrics_util.h"
namespace {
typedef std::map<std::string, std::string> VariationParams;
typedef HUPScoringParams::ScoreBuckets ScoreBuckets;
const char kHUPCullRedirectsFieldTrialName[] = "OmniboxHUPCullRedirects";
const char kHUPCreateShorterMatchFieldTrialName[] =
"OmniboxHUPCreateShorterMatch";
const char kStopTimerFieldTrialName[] = "OmniboxStopTimer";
const char kEnableZeroSuggestGroupPrefix[] = "EnableZeroSuggest";
const char kEnableZeroSuggestMostVisitedGroupPrefix[] =
"EnableZeroSuggestMostVisited";
const char kEnableZeroSuggestAfterTypingGroupPrefix[] =
"EnableZeroSuggestAfterTyping";
const char kEnableZeroSuggestPersonalizedGroupPrefix[] =
"EnableZeroSuggestPersonalized";
const char kAutocompleteDynamicFieldTrialPrefix[] = "AutocompleteDynamicTrial_";
const int kMaxAutocompleteDynamicFieldTrials = 5;
const base::FieldTrial::Probability kHUPCullRedirectsFieldTrialDivisor = 100;
const base::FieldTrial::Probability
kHUPCullRedirectsFieldTrialExperimentFraction = 0;
const base::FieldTrial::Probability
kHUPCreateShorterMatchFieldTrialDivisor = 100;
const base::FieldTrial::Probability
kHUPCreateShorterMatchFieldTrialExperimentFraction = 0;
bool static_field_trials_initialized = false;
int hup_dont_cull_redirects_experiment_group = 0;
int hup_dont_create_shorter_match_experiment_group = 0;
std::string DynamicFieldTrialName(int id) {
return base::StringPrintf("%s%d", kAutocompleteDynamicFieldTrialPrefix, id);
}
void InitializeScoreBuckets(const VariationParams& params,
const char* relevance_cap_param,
const char* half_life_param,
const char* score_buckets_param,
ScoreBuckets* score_buckets) {
VariationParams::const_iterator 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(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()) {
base::StringPairs kv_pairs;
if (base::SplitStringIntoKeyValuePairs(it->second, ':', ',', &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>());
}
}
}
}
HUPScoringParams::ScoreBuckets::ScoreBuckets()
: relevance_cap_(-1),
half_life_days_(-1) {
}
HUPScoringParams::ScoreBuckets::~ScoreBuckets() {
}
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::TimeDelta::FromDays(half_life_days_).InMillisecondsF();
return pow(2.0, -half_life_intervals);
}
void OmniboxFieldTrial::ActivateStaticTrials() {
DCHECK(!static_field_trials_initialized);
scoped_refptr<base::FieldTrial> trial(
base::FieldTrialList::FactoryGetFieldTrial(
kHUPCullRedirectsFieldTrialName, kHUPCullRedirectsFieldTrialDivisor,
"Standard", 2013, 3, 1, base::FieldTrial::ONE_TIME_RANDOMIZED, NULL));
hup_dont_cull_redirects_experiment_group =
trial->AppendGroup("DontCullRedirects",
kHUPCullRedirectsFieldTrialExperimentFraction);
trial = base::FieldTrialList::FactoryGetFieldTrial(
kHUPCreateShorterMatchFieldTrialName,
kHUPCreateShorterMatchFieldTrialDivisor, "Standard", 2013, 3, 1,
base::FieldTrial::ONE_TIME_RANDOMIZED, NULL);
hup_dont_create_shorter_match_experiment_group =
trial->AppendGroup("DontCreateShorterMatch",
kHUPCreateShorterMatchFieldTrialExperimentFraction);
static_field_trials_initialized = true;
}
void OmniboxFieldTrial::ActivateDynamicTrials() {
for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i)
base::FieldTrialList::FindValue(DynamicFieldTrialName(i));
}
int OmniboxFieldTrial::GetDisabledProviderTypes() {
ActivateDynamicTrials();
int provider_types = 0;
for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i) {
std::string group_name = base::FieldTrialList::FindFullName(
DynamicFieldTrialName(i));
const char kDisabledProviders[] = "DisabledProviders_";
if (!StartsWithASCII(group_name, kDisabledProviders, true))
continue;
int types = 0;
if (!base::StringToInt(base::StringPiece(
group_name.substr(strlen(kDisabledProviders))), &types))
continue;
provider_types |= types;
}
return provider_types;
}
void OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(
std::vector<uint32>* field_trial_hashes) {
field_trial_hashes->clear();
for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i) {
const std::string& trial_name = DynamicFieldTrialName(i);
if (base::FieldTrialList::TrialExists(trial_name))
field_trial_hashes->push_back(metrics::HashName(trial_name));
}
if (base::FieldTrialList::TrialExists(kBundledExperimentFieldTrialName)) {
field_trial_hashes->push_back(
metrics::HashName(kBundledExperimentFieldTrialName));
}
}
bool OmniboxFieldTrial::InHUPCullRedirectsFieldTrial() {
return base::FieldTrialList::TrialExists(kHUPCullRedirectsFieldTrialName);
}
bool OmniboxFieldTrial::InHUPCullRedirectsFieldTrialExperimentGroup() {
if (!base::FieldTrialList::TrialExists(kHUPCullRedirectsFieldTrialName))
return false;
const int group = base::FieldTrialList::FindValue(
kHUPCullRedirectsFieldTrialName);
return group == hup_dont_cull_redirects_experiment_group;
}
bool OmniboxFieldTrial::InHUPCreateShorterMatchFieldTrial() {
return
base::FieldTrialList::TrialExists(kHUPCreateShorterMatchFieldTrialName);
}
bool OmniboxFieldTrial::InHUPCreateShorterMatchFieldTrialExperimentGroup() {
if (!base::FieldTrialList::TrialExists(kHUPCreateShorterMatchFieldTrialName))
return false;
const int group = base::FieldTrialList::FindValue(
kHUPCreateShorterMatchFieldTrialName);
return group == hup_dont_create_shorter_match_experiment_group;
}
base::TimeDelta OmniboxFieldTrial::StopTimerFieldTrialDuration() {
int stop_timer_ms;
if (base::StringToInt(
base::FieldTrialList::FindFullName(kStopTimerFieldTrialName),
&stop_timer_ms))
return base::TimeDelta::FromMilliseconds(stop_timer_ms);
return base::TimeDelta::FromMilliseconds(1500);
}
bool OmniboxFieldTrial::HasDynamicFieldTrialGroupPrefix(
const char* group_prefix) {
ActivateDynamicTrials();
for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i) {
const std::string& group_name = base::FieldTrialList::FindFullName(
DynamicFieldTrialName(i));
if (StartsWithASCII(group_name, group_prefix, true))
return true;
}
return false;
}
bool OmniboxFieldTrial::InZeroSuggestFieldTrial() {
return HasDynamicFieldTrialGroupPrefix(kEnableZeroSuggestGroupPrefix) ||
chrome_variations::GetVariationParamValue(
kBundledExperimentFieldTrialName, kZeroSuggestRule) == "true";
}
bool OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial() {
return HasDynamicFieldTrialGroupPrefix(
kEnableZeroSuggestMostVisitedGroupPrefix) ||
chrome_variations::GetVariationParamValue(
kBundledExperimentFieldTrialName,
kZeroSuggestVariantRule) == "MostVisited";
}
bool OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial() {
return HasDynamicFieldTrialGroupPrefix(
kEnableZeroSuggestAfterTypingGroupPrefix) ||
chrome_variations::GetVariationParamValue(
kBundledExperimentFieldTrialName,
kZeroSuggestVariantRule) == "AfterTyping";
}
bool OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() {
return HasDynamicFieldTrialGroupPrefix(
kEnableZeroSuggestPersonalizedGroupPrefix) ||
chrome_variations::GetVariationParamValue(
kBundledExperimentFieldTrialName,
kZeroSuggestVariantRule) == "Personalized";
}
bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
AutocompleteInput::PageClassification current_page_classification,
int* max_relevance) {
const std::string& max_relevance_str =
OmniboxFieldTrial::GetValueForRuleInContext(
kShortcutsScoringMaxRelevanceRule, current_page_classification);
if (max_relevance_str.empty())
return false;
if (!base::StringToInt(max_relevance_str, max_relevance))
return false;
return true;
}
bool OmniboxFieldTrial::SearchHistoryPreventInlining(
AutocompleteInput::PageClassification current_page_classification) {
return OmniboxFieldTrial::GetValueForRuleInContext(
kSearchHistoryRule, current_page_classification) == "PreventInlining";
}
bool OmniboxFieldTrial::SearchHistoryDisable(
AutocompleteInput::PageClassification current_page_classification) {
return OmniboxFieldTrial::GetValueForRuleInContext(
kSearchHistoryRule, current_page_classification) == "Disable";
}
void OmniboxFieldTrial::GetDemotionsByType(
AutocompleteInput::PageClassification current_page_classification,
DemotionMultipliers* demotions_by_type) {
demotions_by_type->clear();
std::string demotion_rule = OmniboxFieldTrial::GetValueForRuleInContext(
kDemoteByTypeRule, current_page_classification);
if (demotion_rule.empty() &&
(current_page_classification ==
AutocompleteInput::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS))
demotion_rule = "1:61,2:61,3:61,4:61,12:61";
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) {
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;
}
}
}
OmniboxFieldTrial::UndemotableTopMatchTypes
OmniboxFieldTrial::GetUndemotableTopTypes(
AutocompleteInput::PageClassification current_page_classification) {
UndemotableTopMatchTypes undemotable_types;
const std::string types_rule =
OmniboxFieldTrial::GetValueForRuleInContext(
kUndemotableTopTypeRule,
current_page_classification);
std::vector<std::string> types;
base::SplitString(types_rule, ',', &types);
for (std::vector<std::string>::const_iterator it = types.begin();
it != types.end(); ++it) {
int t;
base::StringToInt(*it, &t);
undemotable_types.insert(static_cast<AutocompleteMatchType::Type>(t));
}
return undemotable_types;
}
bool OmniboxFieldTrial::ReorderForLegalDefaultMatch(
AutocompleteInput::PageClassification current_page_classification) {
return OmniboxFieldTrial::GetValueForRuleInContext(
kReorderForLegalDefaultMatchRule, current_page_classification) !=
kReorderForLegalDefaultMatchRuleDisabled;
}
void OmniboxFieldTrial::GetExperimentalHUPScoringParams(
HUPScoringParams* scoring_params) {
scoring_params->experimental_scoring_enabled = false;
VariationParams params;
if (!chrome_variations::GetVariationParams(kBundledExperimentFieldTrialName,
¶ms))
return;
VariationParams::const_iterator it = params.find(kHUPNewScoringEnabledParam);
if (it != params.end()) {
int enabled = 0;
if (base::StringToInt(it->second, &enabled))
scoring_params->experimental_scoring_enabled = (enabled != 0);
}
InitializeScoreBuckets(params, kHUPNewScoringTypedCountRelevanceCapParam,
kHUPNewScoringTypedCountHalfLifeTimeParam,
kHUPNewScoringTypedCountScoreBucketsParam,
&scoring_params->typed_count_buckets);
InitializeScoreBuckets(params, kHUPNewScoringVisitedCountRelevanceCapParam,
kHUPNewScoringVisitedCountHalfLifeTimeParam,
kHUPNewScoringVisitedCountScoreBucketsParam,
&scoring_params->visited_count_buckets);
}
int OmniboxFieldTrial::HQPBookmarkValue() {
std::string bookmark_value_str = chrome_variations::
GetVariationParamValue(kBundledExperimentFieldTrialName,
kHQPBookmarkValueRule);
if (bookmark_value_str.empty())
return 1;
int bookmark_value;
base::StringToInt(bookmark_value_str, &bookmark_value);
return bookmark_value;
}
bool OmniboxFieldTrial::HQPDiscountFrecencyWhenFewVisits() {
return chrome_variations::GetVariationParamValue(
kBundledExperimentFieldTrialName,
kHQPDiscountFrecencyWhenFewVisitsRule) == "true";
}
bool OmniboxFieldTrial::HQPAllowMatchInTLDValue() {
return chrome_variations::GetVariationParamValue(
kBundledExperimentFieldTrialName,
kHQPAllowMatchInTLDRule) == "true";
}
bool OmniboxFieldTrial::HQPAllowMatchInSchemeValue() {
return chrome_variations::GetVariationParamValue(
kBundledExperimentFieldTrialName,
kHQPAllowMatchInSchemeRule) == "true";
}
const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] =
"OmniboxBundledExperimentV1";
const char OmniboxFieldTrial::kShortcutsScoringMaxRelevanceRule[] =
"ShortcutsScoringMaxRelevance";
const char OmniboxFieldTrial::kSearchHistoryRule[] = "SearchHistory";
const char OmniboxFieldTrial::kDemoteByTypeRule[] = "DemoteByType";
const char OmniboxFieldTrial::kUndemotableTopTypeRule[] = "UndemotableTopTypes";
const char OmniboxFieldTrial::kReorderForLegalDefaultMatchRule[] =
"ReorderForLegalDefaultMatch";
const char OmniboxFieldTrial::kHQPBookmarkValueRule[] =
"HQPBookmarkValue";
const char OmniboxFieldTrial::kHQPDiscountFrecencyWhenFewVisitsRule[] =
"HQPDiscountFrecencyWhenFewVisits";
const char OmniboxFieldTrial::kHQPAllowMatchInTLDRule[] = "HQPAllowMatchInTLD";
const char OmniboxFieldTrial::kHQPAllowMatchInSchemeRule[] =
"HQPAllowMatchInScheme";
const char OmniboxFieldTrial::kZeroSuggestRule[] = "ZeroSuggest";
const char OmniboxFieldTrial::kZeroSuggestVariantRule[] = "ZeroSuggestVariant";
const char OmniboxFieldTrial::kReorderForLegalDefaultMatchRuleDisabled[] =
"DontReorderForLegalDefaultMatch";
const char OmniboxFieldTrial::kHUPNewScoringEnabledParam[] =
"HUPExperimentalScoringEnabled";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam[] =
"TypedCountRelevanceCap";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam[] =
"TypedCountHalfLifeTime";
const char OmniboxFieldTrial::kHUPNewScoringTypedCountScoreBucketsParam[] =
"TypedCountScoreBuckets";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountRelevanceCapParam[] =
"VisitedCountRelevanceCap";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountHalfLifeTimeParam[] =
"VisitedCountHalfLifeTime";
const char OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam[] =
"VisitedCountScoreBuckets";
std::string OmniboxFieldTrial::GetValueForRuleInContext(
const std::string& rule,
AutocompleteInput::PageClassification page_classification) {
VariationParams params;
if (!chrome_variations::GetVariationParams(kBundledExperimentFieldTrialName,
¶ms)) {
return std::string();
}
const std::string page_classification_str =
base::IntToString(static_cast<int>(page_classification));
const std::string instant_extended =
chrome::IsInstantExtendedAPIEnabled() ? "1" : "0";
VariationParams::const_iterator it = params.find(
rule + ":" + page_classification_str + ":" + instant_extended);
if (it != params.end())
return it->second;
it = params.find(rule + ":*:" + instant_extended);
if (it != params.end())
return it->second;
it = params.find(rule + ":" + page_classification_str + ":*");
if (it != params.end())
return it->second;
it = params.find(rule + ":*:*");
return (it != params.end()) ? it->second : std::string();
}