omnibox_field_trial.cc revision d3868032626d59662ff73b372b5d584c1d144c53
1// Copyright (c) 2012 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 "chrome/browser/omnibox/omnibox_field_trial.h"
6
7#include <string>
8
9#include "base/metrics/field_trial.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_util.h"
12#include "base/strings/stringprintf.h"
13#include "chrome/common/metrics/metrics_util.h"
14#include "chrome/common/metrics/variations/variation_ids.h"
15#include "chrome/common/metrics/variations/variations_util.h"
16
17namespace {
18
19// Field trial names.
20const char kHUPCullRedirectsFieldTrialName[] = "OmniboxHUPCullRedirects";
21const char kHUPCreateShorterMatchFieldTrialName[] =
22    "OmniboxHUPCreateShorterMatch";
23const char kStopTimerFieldTrialName[] = "OmniboxStopTimer";
24const char kShortcutsScoringFieldTrialName[] = "OmniboxShortcutsScoring";
25const char kSearchHistoryFieldTrialName[] = "OmniboxSearchHistory";
26
27// The autocomplete dynamic field trial name prefix.  Each field trial is
28// configured dynamically and is retrieved automatically by Chrome during
29// the startup.
30const char kAutocompleteDynamicFieldTrialPrefix[] = "AutocompleteDynamicTrial_";
31// The maximum number of the autocomplete dynamic field trials (aka layers).
32const int kMaxAutocompleteDynamicFieldTrials = 5;
33
34// Field trial experiment probabilities.
35
36// For HistoryURL provider cull redirects field trial, put 0% ( = 0/100 )
37// of the users in the don't-cull-redirects experiment group.
38// TODO(mpearson): Remove this field trial and the code it uses once I'm
39// sure it's no longer needed.
40const base::FieldTrial::Probability kHUPCullRedirectsFieldTrialDivisor = 100;
41const base::FieldTrial::Probability
42    kHUPCullRedirectsFieldTrialExperimentFraction = 0;
43
44// For HistoryURL provider create shorter match field trial, put 0%
45// ( = 25/100 ) of the users in the don't-create-a-shorter-match
46// experiment group.
47// TODO(mpearson): Remove this field trial and the code it uses once I'm
48// sure it's no longer needed.
49const base::FieldTrial::Probability
50    kHUPCreateShorterMatchFieldTrialDivisor = 100;
51const base::FieldTrial::Probability
52    kHUPCreateShorterMatchFieldTrialExperimentFraction = 0;
53
54// Experiment group names.
55
56const char kStopTimerExperimentGroupName[] = "UseStopTimer";
57
58// Field trial IDs.
59// Though they are not literally "const", they are set only once, in
60// ActivateStaticTrials() below.
61
62// Whether the static field trials have been initialized by
63// ActivateStaticTrials() method.
64bool static_field_trials_initialized = false;
65
66// Field trial ID for the HistoryURL provider cull redirects experiment group.
67int hup_dont_cull_redirects_experiment_group = 0;
68
69// Field trial ID for the HistoryURL provider create shorter match
70// experiment group.
71int hup_dont_create_shorter_match_experiment_group = 0;
72
73
74// Concatenates the autocomplete dynamic field trial prefix with a field trial
75// ID to form a complete autocomplete field trial name.
76std::string DynamicFieldTrialName(int id) {
77  return base::StringPrintf("%s%d", kAutocompleteDynamicFieldTrialPrefix, id);
78}
79
80}  // namespace
81
82
83void OmniboxFieldTrial::ActivateStaticTrials() {
84  DCHECK(!static_field_trials_initialized);
85
86  // Create the HistoryURL provider cull redirects field trial.
87  // Make it expire on March 1, 2013.
88  scoped_refptr<base::FieldTrial> trial(
89      base::FieldTrialList::FactoryGetFieldTrial(
90          kHUPCullRedirectsFieldTrialName, kHUPCullRedirectsFieldTrialDivisor,
91          "Standard", 2013, 3, 1, base::FieldTrial::ONE_TIME_RANDOMIZED, NULL));
92  hup_dont_cull_redirects_experiment_group =
93      trial->AppendGroup("DontCullRedirects",
94                         kHUPCullRedirectsFieldTrialExperimentFraction);
95
96  // Create the HistoryURL provider create shorter match field trial.
97  // Make it expire on March 1, 2013.
98  trial = base::FieldTrialList::FactoryGetFieldTrial(
99      kHUPCreateShorterMatchFieldTrialName,
100      kHUPCreateShorterMatchFieldTrialDivisor, "Standard", 2013, 3, 1,
101      base::FieldTrial::ONE_TIME_RANDOMIZED, NULL);
102  hup_dont_create_shorter_match_experiment_group =
103      trial->AppendGroup("DontCreateShorterMatch",
104                         kHUPCreateShorterMatchFieldTrialExperimentFraction);
105
106  static_field_trials_initialized = true;
107}
108
109void OmniboxFieldTrial::ActivateDynamicTrials() {
110  // Initialize all autocomplete dynamic field trials.  This method may be
111  // called multiple times.
112  for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i)
113    base::FieldTrialList::FindValue(DynamicFieldTrialName(i));
114}
115
116int OmniboxFieldTrial::GetDisabledProviderTypes() {
117  // Make sure that Autocomplete dynamic field trials are activated.  It's OK to
118  // call this method multiple times.
119  ActivateDynamicTrials();
120
121  // Look for group names in form of "DisabledProviders_<mask>" where "mask"
122  // is a bitmap of disabled provider types (AutocompleteProvider::Type).
123  int provider_types = 0;
124  for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i) {
125    std::string group_name = base::FieldTrialList::FindFullName(
126        DynamicFieldTrialName(i));
127    const char kDisabledProviders[] = "DisabledProviders_";
128    if (!StartsWithASCII(group_name, kDisabledProviders, true))
129      continue;
130    int types = 0;
131    if (!base::StringToInt(base::StringPiece(
132            group_name.substr(strlen(kDisabledProviders))), &types)) {
133      LOG(WARNING) << "Malformed DisabledProviders string: " << group_name;
134      continue;
135    }
136    if (types == 0)
137      LOG(WARNING) << "Expecting a non-zero bitmap; group = " << group_name;
138    else
139      provider_types |= types;
140  }
141  return provider_types;
142}
143
144void OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(
145    std::vector<uint32>* field_trial_hashes) {
146  field_trial_hashes->clear();
147  for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i) {
148    const std::string& trial_name = DynamicFieldTrialName(i);
149    if (base::FieldTrialList::TrialExists(trial_name))
150      field_trial_hashes->push_back(metrics::HashName(trial_name));
151  }
152}
153
154bool OmniboxFieldTrial::InHUPCullRedirectsFieldTrial() {
155  return base::FieldTrialList::TrialExists(kHUPCullRedirectsFieldTrialName);
156}
157
158bool OmniboxFieldTrial::InHUPCullRedirectsFieldTrialExperimentGroup() {
159  if (!base::FieldTrialList::TrialExists(kHUPCullRedirectsFieldTrialName))
160    return false;
161
162  // Return true if we're in the experiment group.
163  const int group = base::FieldTrialList::FindValue(
164      kHUPCullRedirectsFieldTrialName);
165  return group == hup_dont_cull_redirects_experiment_group;
166}
167
168bool OmniboxFieldTrial::InHUPCreateShorterMatchFieldTrial() {
169  return
170      base::FieldTrialList::TrialExists(kHUPCreateShorterMatchFieldTrialName);
171}
172
173bool OmniboxFieldTrial::InHUPCreateShorterMatchFieldTrialExperimentGroup() {
174  if (!base::FieldTrialList::TrialExists(kHUPCreateShorterMatchFieldTrialName))
175    return false;
176
177  // Return true if we're in the experiment group.
178  const int group = base::FieldTrialList::FindValue(
179      kHUPCreateShorterMatchFieldTrialName);
180  return group == hup_dont_create_shorter_match_experiment_group;
181}
182
183bool OmniboxFieldTrial::InStopTimerFieldTrialExperimentGroup() {
184  return (base::FieldTrialList::FindFullName(kStopTimerFieldTrialName) ==
185          kStopTimerExperimentGroupName);
186}
187
188bool OmniboxFieldTrial::InZeroSuggestFieldTrial() {
189  // Make sure that Autocomplete dynamic field trials are activated.  It's OK to
190  // call this method multiple times.
191  ActivateDynamicTrials();
192
193  // Look for group names starting with "EnableZeroSuggest"
194  for (int i = 0; i < kMaxAutocompleteDynamicFieldTrials; ++i) {
195    const std::string& group_name = base::FieldTrialList::FindFullName(
196        DynamicFieldTrialName(i));
197    const char kEnableZeroSuggest[] = "EnableZeroSuggest";
198    if (StartsWithASCII(group_name, kEnableZeroSuggest, true))
199      return true;
200  }
201  return false;
202}
203
204// If the active group name starts with "MaxRelevance_", extract the
205// int that immediately following that, returning true on success.
206bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(int* max_relevance) {
207  std::string group_name =
208      base::FieldTrialList::FindFullName(kShortcutsScoringFieldTrialName);
209  const char kMaxRelevanceGroupPrefix[] = "MaxRelevance_";
210  if (!StartsWithASCII(group_name, kMaxRelevanceGroupPrefix, true))
211    return false;
212  if (!base::StringToInt(base::StringPiece(
213          group_name.substr(strlen(kMaxRelevanceGroupPrefix))),
214                         max_relevance)) {
215    LOG(WARNING) << "Malformed MaxRelevance string: " << group_name;
216    return false;
217  }
218  return true;
219}
220
221bool OmniboxFieldTrial::SearchHistoryPreventInlining() {
222  return (base::FieldTrialList::FindFullName(kSearchHistoryFieldTrialName) ==
223          "PreventInlining");
224}
225
226bool OmniboxFieldTrial::SearchHistoryDisable() {
227  return (base::FieldTrialList::FindFullName(kSearchHistoryFieldTrialName) ==
228          "Disable");
229}
230