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