blob: da169432c186c24c658299bacdf43e67d94fe015 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include <string>
#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/common/metrics/metrics_util.h"
#include "chrome/common/metrics/variations/variation_ids.h"
#include "chrome/common/metrics/variations/variations_util.h"
namespace {
// Field trial names.
const char kDisallowInlineHQPFieldTrialName[] = "OmniboxDisallowInlineHQP";
const char kHUPCullRedirectsFieldTrialName[] = "OmniboxHUPCullRedirects";
const char kHUPCreateShorterMatchFieldTrialName[] =
"OmniboxHUPCreateShorterMatch";
const char kStopTimerFieldTrialName[] = "OmniboxStopTimer";
const char kShortcutsScoringFieldTrialName[] = "OmniboxShortcutsScoring";
// The autocomplete dynamic field trial name prefix. Each field trial is
// configured dynamically and is retrieved automatically by Chrome during
// the startup.
const char kAutocompleteDynamicFieldTrialPrefix[] = "AutocompleteDynamicTrial_";
// The maximum number of the autocomplete dynamic field trials (aka layers).
const int kMaxAutocompleteDynamicFieldTrials = 5;
// Field trial experiment probabilities.
// For inline History Quick Provider field trial, put 0% ( = 0/100 )
// of the users in the disallow-inline experiment group.
const base::FieldTrial::Probability kDisallowInlineHQPFieldTrialDivisor = 100;
const base::FieldTrial::Probability
kDisallowInlineHQPFieldTrialExperimentFraction = 0;
// For HistoryURL provider cull redirects field trial, put 0% ( = 0/100 )
// of the users in the don't-cull-redirects experiment group.
// TODO(mpearson): Remove this field trial and the code it uses once I'm
// sure it's no longer needed.
const base::FieldTrial::Probability kHUPCullRedirectsFieldTrialDivisor = 100;
const base::FieldTrial::Probability
kHUPCullRedirectsFieldTrialExperimentFraction = 0;
// For HistoryURL provider create shorter match field trial, put 0%
// ( = 25/100 ) of the users in the don't-create-a-shorter-match
// experiment group.
// TODO(mpearson): Remove this field trial and the code it uses once I'm
// sure it's no longer needed.
const base::FieldTrial::Probability
kHUPCreateShorterMatchFieldTrialDivisor = 100;
const base::FieldTrial::Probability
kHUPCreateShorterMatchFieldTrialExperimentFraction = 0;
// Experiment group names.
const char kStopTimerExperimentGroupName[] = "UseStopTimer";
// Field trial IDs.
// Though they are not literally "const", they are set only once, in
// ActivateStaticTrials() below.
// Whether the static field trials have been initialized by
// ActivateStaticTrials() method.
bool static_field_trials_initialized = false;
// Field trial ID for the disallow-inline History Quick Provider
// experiment group.
int disallow_inline_hqp_experiment_group = 0;
// Field trial ID for the HistoryURL provider cull redirects experiment group.
int hup_dont_cull_redirects_experiment_group = 0;
// Field trial ID for the HistoryURL provider create shorter match
// experiment group.
int hup_dont_create_shorter_match_experiment_group = 0;
// Concatenates the autocomplete dynamic field trial prefix with a field trial
// ID to form a complete autocomplete field trial name.
std::string DynamicFieldTrialName(int id) {
return base::StringPrintf("%s%d", kAutocompleteDynamicFieldTrialPrefix, id);
}
} // namespace
void OmniboxFieldTrial::ActivateStaticTrials() {
DCHECK(!static_field_trials_initialized);
// Create inline History Quick Provider field trial.
// Make it expire on November 8, 2012.
scoped_refptr<base::FieldTrial> trial(
base::FieldTrialList::FactoryGetFieldTrial(
kDisallowInlineHQPFieldTrialName, kDisallowInlineHQPFieldTrialDivisor,
"Standard", 2012, 11, 8, NULL));
// Because users tend to use omnibox without attention to it--habits
// get ingrained, users tend to learn that a particular suggestion is
// at a particular spot in the drop-down--we're going to make these
// field trials sticky. We want users to stay in them once assigned
// so they have a better experience and also so we don't get weird
// effects as omnibox ranking keeps changing and users learn they can't
// trust the omnibox.
trial->UseOneTimeRandomization();
disallow_inline_hqp_experiment_group = trial->AppendGroup("DisallowInline",
kDisallowInlineHQPFieldTrialExperimentFraction);
// Create the HistoryURL provider cull redirects field trial.
// Make it expire on March 1, 2013.
trial = base::FieldTrialList::FactoryGetFieldTrial(
kHUPCullRedirectsFieldTrialName, kHUPCullRedirectsFieldTrialDivisor,
"Standard", 2013, 3, 1, NULL);
trial->UseOneTimeRandomization();
hup_dont_cull_redirects_experiment_group =
trial->AppendGroup("DontCullRedirects",
kHUPCullRedirectsFieldTrialExperimentFraction);
// Create the HistoryURL provider create shorter match field trial.
// Make it expire on March 1, 2013.
trial = base::FieldTrialList::FactoryGetFieldTrial(
kHUPCreateShorterMatchFieldTrialName,
kHUPCreateShorterMatchFieldTrialDivisor, "Standard", 2013, 3, 1, NULL);
trial->UseOneTimeRandomization();
hup_dont_create_shorter_match_experiment_group =
trial->AppendGroup("DontCreateShorterMatch",
kHUPCreateShorterMatchFieldTrialExperimentFraction);
static_field_trials_initialized = true;
}
void OmniboxFieldTrial::ActivateDynamicTrials() {
// Initialize all autocomplete dynamic field trials. This method may be
// called multiple times.
for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i)
base::FieldTrialList::FindValue(DynamicFieldTrialName(i));
}
int OmniboxFieldTrial::GetDisabledProviderTypes() {
// Make sure that Autocomplete dynamic field trials are activated. It's OK to
// call this method multiple times.
ActivateDynamicTrials();
// Look for group names in form of "DisabledProviders_<mask>" where "mask"
// is a bitmap of disabled provider types (AutocompleteProvider::Type).
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)) {
LOG(WARNING) << "Malformed DisabledProviders string: " << group_name;
continue;
}
if (types == 0)
LOG(WARNING) << "Expecting a non-zero bitmap; group = " << group_name;
else
provider_types |= types;
}
return provider_types;
}
bool OmniboxFieldTrial::InDisallowInlineHQPFieldTrial() {
return base::FieldTrialList::TrialExists(kDisallowInlineHQPFieldTrialName);
}
bool OmniboxFieldTrial::InDisallowInlineHQPFieldTrialExperimentGroup() {
if (!base::FieldTrialList::TrialExists(kDisallowInlineHQPFieldTrialName))
return false;
// Return true if we're in the experiment group.
const int group = base::FieldTrialList::FindValue(
kDisallowInlineHQPFieldTrialName);
return group == disallow_inline_hqp_experiment_group;
}
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));
}
}
bool OmniboxFieldTrial::InHUPCullRedirectsFieldTrial() {
return base::FieldTrialList::TrialExists(kHUPCullRedirectsFieldTrialName);
}
bool OmniboxFieldTrial::InHUPCullRedirectsFieldTrialExperimentGroup() {
if (!base::FieldTrialList::TrialExists(kHUPCullRedirectsFieldTrialName))
return false;
// Return true if we're in the experiment group.
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;
// Return true if we're in the experiment group.
const int group = base::FieldTrialList::FindValue(
kHUPCreateShorterMatchFieldTrialName);
return group == hup_dont_create_shorter_match_experiment_group;
}
bool OmniboxFieldTrial::InStopTimerFieldTrialExperimentGroup() {
return (base::FieldTrialList::FindFullName(kStopTimerFieldTrialName) ==
kStopTimerExperimentGroupName);
}
bool OmniboxFieldTrial::InZeroSuggestFieldTrial() {
// Make sure that Autocomplete dynamic field trials are activated. It's OK to
// call this method multiple times.
ActivateDynamicTrials();
// Look for group names starting with "EnableZeroSuggest"
for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i) {
const std::string& group_name = base::FieldTrialList::FindFullName(
DynamicFieldTrialName(i));
const char kEnableZeroSuggest[] = "EnableZeroSuggest";
if (StartsWithASCII(group_name, kEnableZeroSuggest, true))
return true;
}
return false;
}
// If the active group name starts with "MaxRelevance_", extract the
// int that immediately following that, returning true on success.
bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(int* max_relevance) {
std::string group_name =
base::FieldTrialList::FindFullName(kShortcutsScoringFieldTrialName);
const char kMaxRelevanceGroupPrefix[] = "MaxRelevance_";
if (!StartsWithASCII(group_name, kMaxRelevanceGroupPrefix, true))
return false;
if (!base::StringToInt(base::StringPiece(
group_name.substr(strlen(kMaxRelevanceGroupPrefix))),
max_relevance)) {
LOG(WARNING) << "Malformed MaxRelevance string: " << group_name;
return false;
}
return true;
}