| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/instant/instant_field_trial.h" | 5 #include "chrome/browser/instant/instant_field_trial.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "chrome/browser/metrics/metrics_service.h" | 9 #include "chrome/browser/metrics/metrics_service.h" |
| 10 #include "chrome/browser/prefs/pref_service.h" | 10 #include "chrome/browser/prefs/pref_service.h" |
| 11 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
| 12 #include "chrome/common/chrome_switches.h" | 12 #include "chrome/common/chrome_switches.h" |
| 13 #include "chrome/common/pref_names.h" | 13 #include "chrome/common/pref_names.h" |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 // Field trial IDs of the control and experiment groups. Though they are not | 17 // IDs of the field trial groups. Though they are not literally "const", they |
| 18 // literally "const", they are set only once, in Activate() below. See the .h | 18 // are set only once, in Activate() below. |
| 19 // file for what these groups represent. | |
| 20 int g_inactive = -1; | |
| 21 int g_instant = 0; | 19 int g_instant = 0; |
| 22 int g_suggest = 0; | 20 int g_suggest = 0; |
| 23 int g_hidden = 0; | 21 int g_hidden = 0; |
| 24 int g_silent = 0; | 22 int g_silent = 0; |
| 25 int g_control = 0; | 23 int g_control = 0; |
| 26 | 24 |
| 27 } | 25 } |
| 28 | 26 |
| 29 // static | 27 // static |
| 30 void InstantFieldTrial::Activate() { | 28 void InstantFieldTrial::Activate() { |
| 31 scoped_refptr<base::FieldTrial> trial( | 29 scoped_refptr<base::FieldTrial> trial( |
| 32 base::FieldTrialList::FactoryGetFieldTrial( | 30 base::FieldTrialList::FactoryGetFieldTrial( |
| 33 "Instant", 1000, "Inactive", 2013, 7, 1, &g_inactive)); | 31 "Instant", 1000, "CONTROL", 2013, 7, 1, &g_control)); |
| 34 | 32 |
| 35 // Try to give the user a consistent experience, if possible. | 33 // Try to give the user a consistent experience, if possible. |
| 36 if (base::FieldTrialList::IsOneTimeRandomizationEnabled()) | 34 if (base::FieldTrialList::IsOneTimeRandomizationEnabled()) |
| 37 trial->UseOneTimeRandomization(); | 35 trial->UseOneTimeRandomization(); |
| 38 | 36 |
| 39 g_instant = trial->AppendGroup("Instant", 10); // 1% | 37 // Though each group (including CONTROL) is nominally at 20%, GetMode() |
| 40 g_suggest = trial->AppendGroup("Suggest", 10); // 1% | 38 // often returns SILENT. See below for details. |
| 41 g_hidden = trial->AppendGroup("Hidden", 960); // 96% | 39 g_instant = trial->AppendGroup("INSTANT", 200); // 20% |
| 42 g_silent = trial->AppendGroup("Silent", 10); // 1% | 40 g_suggest = trial->AppendGroup("SUGGEST", 200); // 20% |
| 43 g_control = trial->AppendGroup("Control", 10); // 1% | 41 g_hidden = trial->AppendGroup("HIDDEN", 200); // 20% |
| 42 g_silent = trial->AppendGroup("SILENT", 200); // 20% |
| 44 } | 43 } |
| 45 | 44 |
| 46 // static | 45 // static |
| 47 InstantFieldTrial::Group InstantFieldTrial::GetGroup(Profile* profile) { | 46 InstantFieldTrial::Mode InstantFieldTrial::GetMode(Profile* profile) { |
| 48 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 47 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 49 if (command_line->HasSwitch(switches::kInstantFieldTrial)) { | 48 if (command_line->HasSwitch(switches::kInstantFieldTrial)) { |
| 50 std::string switch_value = | 49 std::string switch_value = |
| 51 command_line->GetSwitchValueASCII(switches::kInstantFieldTrial); | 50 command_line->GetSwitchValueASCII(switches::kInstantFieldTrial); |
| 52 if (switch_value == switches::kInstantFieldTrialInstant) | 51 if (switch_value == switches::kInstantFieldTrialInstant) |
| 53 return INSTANT; | 52 return INSTANT; |
| 54 if (switch_value == switches::kInstantFieldTrialSuggest) | 53 if (switch_value == switches::kInstantFieldTrialSuggest) |
| 55 return SUGGEST; | 54 return SUGGEST; |
| 56 if (switch_value == switches::kInstantFieldTrialHidden) | 55 if (switch_value == switches::kInstantFieldTrialHidden) |
| 57 return HIDDEN; | 56 return HIDDEN; |
| 58 if (switch_value == switches::kInstantFieldTrialSilent) | 57 if (switch_value == switches::kInstantFieldTrialSilent) |
| 59 return SILENT; | 58 return SILENT; |
| 60 if (switch_value == switches::kInstantFieldTrialControl) | 59 return CONTROL; |
| 61 return CONTROL; | |
| 62 return INACTIVE; | |
| 63 } | 60 } |
| 64 | 61 |
| 65 const int group = base::FieldTrialList::FindValue("Instant"); | 62 // Instant explicitly enabled in chrome://settings. |
| 66 if (group == base::FieldTrial::kNotFinalized || group == g_inactive) | |
| 67 return INACTIVE; | |
| 68 | |
| 69 // If Instant is already enabled explicitly, then it's not a field trial. | |
| 70 const PrefService* prefs = profile ? profile->GetPrefs() : NULL; | 63 const PrefService* prefs = profile ? profile->GetPrefs() : NULL; |
| 71 if (prefs && prefs->GetBoolean(prefs::kInstantEnabled)) | 64 if (prefs && prefs->GetBoolean(prefs::kInstantEnabled)) |
| 72 return INACTIVE; | 65 return INSTANT; |
| 73 | 66 |
| 74 // CONTROL and SILENT are unconstrained. | 67 const int group = base::FieldTrialList::FindValue("Instant"); |
| 75 if (group == g_control) | 68 if (group == base::FieldTrial::kNotFinalized || group == g_control) |
| 76 return CONTROL; | 69 return CONTROL; |
| 77 if (group == g_silent) | |
| 78 return SILENT; | |
| 79 | 70 |
| 80 // HIDDEN, SUGGEST and INSTANT need non-incognito, suggest-enabled profiles. | 71 // HIDDEN, SUGGEST and INSTANT need non-incognito, suggest-enabled, UMA |
| 81 if (!prefs || profile->IsOffTheRecord() || | 72 // opted-in profiles. |
| 82 !prefs->GetBoolean(prefs::kSearchSuggestEnabled)) { | 73 if (prefs && !profile->IsOffTheRecord() && |
| 83 return INACTIVE; | 74 prefs->GetBoolean(prefs::kSearchSuggestEnabled) && |
| 75 MetricsServiceHelper::IsMetricsReportingEnabled()) { |
| 76 if (group == g_hidden) |
| 77 return HIDDEN; |
| 78 if (group == g_suggest) |
| 79 return SUGGEST; |
| 80 |
| 81 // INSTANT also requires no group policy override and no explicit opt-out. |
| 82 if (!prefs->IsManagedPreference(prefs::kInstantEnabled) && |
| 83 !prefs->GetBoolean(prefs::kInstantEnabledOnce)) { |
| 84 if (group == g_instant) |
| 85 return INSTANT; |
| 86 } |
| 84 } | 87 } |
| 85 | 88 |
| 86 if (group == g_hidden) | 89 // Default is SILENT. This will be returned for most users (for example, even |
| 87 return HIDDEN; | 90 // if a user falls into another group, but has suggest or UMA disabled). |
| 88 | 91 return SILENT; |
| 89 // SUGGEST and INSTANT require UMA opt-in. | |
| 90 if (!MetricsServiceHelper::IsMetricsReportingEnabled()) | |
| 91 return INACTIVE; | |
| 92 | |
| 93 if (group == g_suggest) | |
| 94 return SUGGEST; | |
| 95 | |
| 96 // Disable INSTANT for group policy overrides and explicit opt-out. | |
| 97 if (prefs->IsManagedPreference(prefs::kInstantEnabled) || | |
| 98 prefs->GetBoolean(prefs::kInstantEnabledOnce)) { | |
| 99 return INACTIVE; | |
| 100 } | |
| 101 | |
| 102 if (group == g_instant) | |
| 103 return INSTANT; | |
| 104 | |
| 105 NOTREACHED(); | |
| 106 return INACTIVE; | |
| 107 } | 92 } |
| 108 | 93 |
| 109 // static | 94 // static |
| 110 bool InstantFieldTrial::IsInstantExperiment(Profile* profile) { | 95 std::string InstantFieldTrial::GetModeAsString(Profile* profile) { |
| 111 Group group = GetGroup(profile); | 96 const Mode mode = GetMode(profile); |
| 112 return group == INSTANT || group == SUGGEST || group == HIDDEN || | 97 switch (mode) { |
| 113 group == SILENT; | 98 case INSTANT: return "_Instant"; |
| 114 } | 99 case SUGGEST: return "_Suggest"; |
| 115 | 100 case HIDDEN: return "_Hidden"; |
| 116 // static | 101 case SILENT: return "_Silent"; |
| 117 bool InstantFieldTrial::IsHiddenExperiment(Profile* profile) { | 102 case CONTROL: return std::string(); |
| 118 Group group = GetGroup(profile); | |
| 119 return group == SUGGEST || group == HIDDEN || group == SILENT; | |
| 120 } | |
| 121 | |
| 122 // static | |
| 123 bool InstantFieldTrial::IsSilentExperiment(Profile* profile) { | |
| 124 Group group = GetGroup(profile); | |
| 125 return group == SILENT; | |
| 126 } | |
| 127 | |
| 128 // static | |
| 129 std::string InstantFieldTrial::GetGroupName(Profile* profile) { | |
| 130 switch (GetGroup(profile)) { | |
| 131 case INACTIVE: return std::string(); | |
| 132 case INSTANT: return "_Instant"; | |
| 133 case SUGGEST: return "_Suggest"; | |
| 134 case HIDDEN: return "_Hidden"; | |
| 135 case SILENT: return "_Silent"; | |
| 136 case CONTROL: return "_Control"; | |
| 137 } | 103 } |
| 138 | 104 |
| 139 NOTREACHED(); | 105 NOTREACHED(); |
| 140 return std::string(); | 106 return std::string(); |
| 141 } | 107 } |
| 142 | |
| 143 // static | |
| 144 std::string InstantFieldTrial::GetGroupAsUrlParam(Profile* profile) { | |
| 145 switch (GetGroup(profile)) { | |
| 146 case INACTIVE: return std::string(); | |
| 147 case INSTANT: return "ix=i9&"; | |
| 148 case SUGGEST: return "ix=t9&"; | |
| 149 case HIDDEN: return "ix=h9&"; | |
| 150 case SILENT: return "ix=s9&"; | |
| 151 case CONTROL: return "ix=c9&"; | |
| 152 } | |
| 153 | |
| 154 NOTREACHED(); | |
| 155 return std::string(); | |
| 156 } | |
| 157 | |
| 158 // static | |
| 159 bool InstantFieldTrial::ShouldSetSuggestedText(Profile* profile) { | |
| 160 Group group = GetGroup(profile); | |
| 161 return group != HIDDEN && group != SILENT; | |
| 162 } | |
| OLD | NEW |