prerender_field_trial.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/prerender/prerender_field_trial.h" 6 7#include "base/command_line.h" 8#include "base/logging.h" 9#include "base/metrics/field_trial.h" 10#include "base/metrics/histogram.h" 11#include "base/prefs/pref_service.h" 12#include "chrome/browser/metrics/metrics_service.h" 13#include "chrome/browser/predictors/autocomplete_action_predictor.h" 14#include "chrome/browser/prerender/prerender_manager.h" 15#include "chrome/browser/profiles/profile.h" 16#include "chrome/common/chrome_switches.h" 17#include "chrome/common/chrome_version_info.h" 18 19using base::FieldTrial; 20using base::FieldTrialList; 21 22namespace prerender { 23 24namespace { 25 26const char kOmniboxTrialName[] = "PrerenderFromOmnibox"; 27int g_omnibox_trial_default_group_number = kint32min; 28 29const char kLocalPredictorTrialName[] = "PrerenderLocalPredictor"; 30const char kLocalPredictorEnabledGroup[] = "Enabled"; 31const char kLocalPredictorDisabledGroup[] = "Disabled"; 32 33const char kLoggedInPredictorTrialName[] = "PrerenderLoggedInPredictor"; 34const char kLoggedInPredictorEnabledGroup[] = "Enabled"; 35const char kLoggedInPredictorDisabledGroup[] = "Disabled"; 36 37const char kSideEffectFreeWhitelistTrialName[] = "SideEffectFreeWhitelist"; 38const char kSideEffectFreeWhitelistEnabledGroup[] = "Enabled"; 39const char kSideEffectFreeWhitelistDisabledGroup[] = "Disabled"; 40 41void SetupPrefetchFieldTrial() { 42 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 43 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 44 channel == chrome::VersionInfo::CHANNEL_BETA) { 45 return; 46 } 47 48 const FieldTrial::Probability divisor = 1000; 49 const FieldTrial::Probability prefetch_probability = 500; 50 scoped_refptr<FieldTrial> trial( 51 FieldTrialList::FactoryGetFieldTrial( 52 "Prefetch", divisor, "ContentPrefetchPrefetchOff", 53 2013, 12, 31, NULL)); 54 const int kPrefetchOnGroup = trial->AppendGroup("ContentPrefetchPrefetchOn", 55 prefetch_probability); 56 PrerenderManager::SetIsPrefetchEnabled(trial->group() == kPrefetchOnGroup); 57} 58 59void SetupPrerenderFieldTrial() { 60 const FieldTrial::Probability divisor = 1000; 61 62 FieldTrial::Probability control_probability; 63 FieldTrial::Probability experiment_multi_prerender_probability; 64 FieldTrial::Probability experiment_15min_ttl_probability; 65 FieldTrial::Probability experiment_no_use_probability; 66 67 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 68 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 69 channel == chrome::VersionInfo::CHANNEL_BETA) { 70 // Use very conservatives and stable settings in beta and stable. 71 const FieldTrial::Probability release_prerender_enabled_probability = 980; 72 const FieldTrial::Probability release_control_probability = 10; 73 const FieldTrial::Probability 74 release_experiment_multi_prerender_probability = 0; 75 const FieldTrial::Probability release_experiment_15min_ttl_probability = 10; 76 const FieldTrial::Probability release_experiment_no_use_probability = 0; 77 COMPILE_ASSERT( 78 release_prerender_enabled_probability + release_control_probability + 79 release_experiment_multi_prerender_probability + 80 release_experiment_15min_ttl_probability + 81 release_experiment_no_use_probability == divisor, 82 release_experiment_probabilities_must_equal_divisor); 83 84 control_probability = release_control_probability; 85 experiment_multi_prerender_probability = 86 release_experiment_multi_prerender_probability; 87 experiment_15min_ttl_probability = release_experiment_15min_ttl_probability; 88 experiment_no_use_probability = release_experiment_no_use_probability; 89 } else { 90 // In testing channels, use more experiments and a larger control group to 91 // improve quality of data. 92 const FieldTrial::Probability dev_prerender_enabled_probability = 250; 93 const FieldTrial::Probability dev_control_probability = 250; 94 const FieldTrial::Probability 95 dev_experiment_multi_prerender_probability = 250; 96 const FieldTrial::Probability dev_experiment_15min_ttl_probability = 125; 97 const FieldTrial::Probability dev_experiment_no_use_probability = 125; 98 COMPILE_ASSERT(dev_prerender_enabled_probability + dev_control_probability + 99 dev_experiment_multi_prerender_probability + 100 dev_experiment_15min_ttl_probability + 101 dev_experiment_no_use_probability == divisor, 102 dev_experiment_probabilities_must_equal_divisor); 103 104 control_probability = dev_control_probability; 105 experiment_multi_prerender_probability = 106 dev_experiment_multi_prerender_probability; 107 experiment_15min_ttl_probability = dev_experiment_15min_ttl_probability; 108 experiment_no_use_probability = dev_experiment_no_use_probability; 109 } 110 111 int prerender_enabled_group = -1; 112 scoped_refptr<FieldTrial> trial( 113 FieldTrialList::FactoryGetFieldTrial( 114 "Prerender", divisor, "PrerenderEnabled", 115 2013, 12, 31, &prerender_enabled_group)); 116 const int control_group = 117 trial->AppendGroup("PrerenderControl", 118 control_probability); 119 const int experiment_multi_prerender_group = 120 trial->AppendGroup("PrerenderMulti", 121 experiment_multi_prerender_probability); 122 const int experiment_15_min_TTL_group = 123 trial->AppendGroup("Prerender15minTTL", 124 experiment_15min_ttl_probability); 125 const int experiment_no_use_group = 126 trial->AppendGroup("PrerenderNoUse", 127 experiment_no_use_probability); 128 129 const int trial_group = trial->group(); 130 if (trial_group == prerender_enabled_group) { 131 PrerenderManager::SetMode( 132 PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP); 133 } else if (trial_group == control_group) { 134 PrerenderManager::SetMode( 135 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP); 136 } else if (trial_group == experiment_multi_prerender_group) { 137 PrerenderManager::SetMode( 138 PrerenderManager::PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP); 139 } else if (trial_group == experiment_15_min_TTL_group) { 140 PrerenderManager::SetMode( 141 PrerenderManager::PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP); 142 } else if (trial_group == experiment_no_use_group) { 143 PrerenderManager::SetMode( 144 PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP); 145 } else { 146 NOTREACHED(); 147 } 148} 149 150} // end namespace 151 152void ConfigureOmniboxPrerender(); 153void ConfigureLocalPredictor(); 154void ConfigureLoggedInPredictor(); 155void ConfigureSideEffectFreeWhitelist(); 156 157void ConfigurePrefetchAndPrerender(const CommandLine& command_line) { 158 enum PrerenderOption { 159 PRERENDER_OPTION_AUTO, 160 PRERENDER_OPTION_DISABLED, 161 PRERENDER_OPTION_ENABLED, 162 PRERENDER_OPTION_PREFETCH_ONLY, 163 }; 164 165 PrerenderOption prerender_option = PRERENDER_OPTION_AUTO; 166 if (command_line.HasSwitch(switches::kPrerenderMode)) { 167 const std::string switch_value = 168 command_line.GetSwitchValueASCII(switches::kPrerenderMode); 169 170 if (switch_value == switches::kPrerenderModeSwitchValueAuto) { 171 prerender_option = PRERENDER_OPTION_AUTO; 172 } else if (switch_value == switches::kPrerenderModeSwitchValueDisabled) { 173 prerender_option = PRERENDER_OPTION_DISABLED; 174 } else if (switch_value.empty() || 175 switch_value == switches::kPrerenderModeSwitchValueEnabled) { 176 // The empty string means the option was provided with no value, and that 177 // means enable. 178 prerender_option = PRERENDER_OPTION_ENABLED; 179 } else if (switch_value == 180 switches::kPrerenderModeSwitchValuePrefetchOnly) { 181 prerender_option = PRERENDER_OPTION_PREFETCH_ONLY; 182 } else { 183 prerender_option = PRERENDER_OPTION_DISABLED; 184 LOG(ERROR) << "Invalid --prerender option received on command line: " 185 << switch_value; 186 LOG(ERROR) << "Disabling prerendering!"; 187 } 188 } 189 190 switch (prerender_option) { 191 case PRERENDER_OPTION_AUTO: 192 SetupPrefetchFieldTrial(); 193 SetupPrerenderFieldTrial(); 194 break; 195 case PRERENDER_OPTION_DISABLED: 196 PrerenderManager::SetIsPrefetchEnabled(false); 197 PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED); 198 break; 199 case PRERENDER_OPTION_ENABLED: 200 PrerenderManager::SetIsPrefetchEnabled(true); 201 PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED); 202 break; 203 case PRERENDER_OPTION_PREFETCH_ONLY: 204 PrerenderManager::SetIsPrefetchEnabled(true); 205 PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED); 206 break; 207 default: 208 NOTREACHED(); 209 } 210 211 ConfigureOmniboxPrerender(); 212 ConfigureLocalPredictor(); 213 ConfigureLoggedInPredictor(); 214 ConfigureSideEffectFreeWhitelist(); 215} 216 217void ConfigureOmniboxPrerender() { 218 // Field trial to see if we're enabled. 219 const FieldTrial::Probability kDivisor = 100; 220 221 FieldTrial::Probability kDisabledProbability = 10; 222 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 223 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 224 channel == chrome::VersionInfo::CHANNEL_BETA) { 225 kDisabledProbability = 1; 226 } 227 scoped_refptr<FieldTrial> omnibox_prerender_trial( 228 FieldTrialList::FactoryGetFieldTrial( 229 kOmniboxTrialName, kDivisor, "OmniboxPrerenderEnabled", 230 2013, 12, 31, &g_omnibox_trial_default_group_number)); 231 omnibox_prerender_trial->AppendGroup("OmniboxPrerenderDisabled", 232 kDisabledProbability); 233} 234 235void ConfigureLocalPredictor() { 236 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 237 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 238 channel == chrome::VersionInfo::CHANNEL_BETA) { 239 return; 240 } 241 scoped_refptr<FieldTrial> local_predictor_trial( 242 FieldTrialList::FactoryGetFieldTrial( 243 kLocalPredictorTrialName, 100, 244 kLocalPredictorDisabledGroup, 2013, 12, 31, NULL)); 245 local_predictor_trial->AppendGroup(kLocalPredictorEnabledGroup, 100); 246} 247 248void ConfigureLoggedInPredictor() { 249 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 250 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 251 channel == chrome::VersionInfo::CHANNEL_BETA) { 252 return; 253 } 254 scoped_refptr<FieldTrial> logged_in_predictor_trial( 255 FieldTrialList::FactoryGetFieldTrial( 256 kLoggedInPredictorTrialName, 100, 257 kLoggedInPredictorDisabledGroup, 2013, 12, 31, NULL)); 258 logged_in_predictor_trial->AppendGroup(kLoggedInPredictorEnabledGroup, 100); 259} 260 261void ConfigureSideEffectFreeWhitelist() { 262 scoped_refptr<FieldTrial> side_effect_free_whitelist_trial( 263 FieldTrialList::FactoryGetFieldTrial( 264 kSideEffectFreeWhitelistTrialName, 100, 265 kSideEffectFreeWhitelistDisabledGroup, 2013, 12, 31, NULL)); 266 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 267 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 268 channel == chrome::VersionInfo::CHANNEL_BETA) { 269 return; 270 } 271 side_effect_free_whitelist_trial->AppendGroup( 272 kSideEffectFreeWhitelistEnabledGroup, 100); 273} 274 275bool IsOmniboxEnabled(Profile* profile) { 276 if (!profile) 277 return false; 278 279 if (!PrerenderManager::IsPrerenderingPossible()) 280 return false; 281 282 // Override any field trial groups if the user has set a command line flag. 283 if (CommandLine::ForCurrentProcess()->HasSwitch( 284 switches::kPrerenderFromOmnibox)) { 285 const std::string switch_value = 286 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 287 switches::kPrerenderFromOmnibox); 288 289 if (switch_value == switches::kPrerenderFromOmniboxSwitchValueEnabled) 290 return true; 291 292 if (switch_value == switches::kPrerenderFromOmniboxSwitchValueDisabled) 293 return false; 294 295 DCHECK(switch_value == switches::kPrerenderFromOmniboxSwitchValueAuto); 296 } 297 298 const int group = FieldTrialList::FindValue(kOmniboxTrialName); 299 return group == FieldTrial::kNotFinalized || 300 group == g_omnibox_trial_default_group_number; 301} 302 303bool IsLocalPredictorEnabled() { 304#if defined(OS_ANDROID) || defined(OS_IOS) 305 return false; 306#endif 307 if (CommandLine::ForCurrentProcess()->HasSwitch( 308 switches::kDisablePrerenderLocalPredictor)) { 309 return false; 310 } 311 return base::FieldTrialList::FindFullName(kLocalPredictorTrialName) == 312 kLocalPredictorEnabledGroup; 313} 314 315bool IsLoggedInPredictorEnabled() { 316 return base::FieldTrialList::FindFullName(kLoggedInPredictorTrialName) == 317 kLoggedInPredictorEnabledGroup; 318} 319 320bool IsSideEffectFreeWhitelistEnabled() { 321 return base::FieldTrialList::FindFullName(kSideEffectFreeWhitelistTrialName) 322 == kSideEffectFreeWhitelistEnabledGroup; 323} 324 325} // namespace prerender 326