Remove the dependency of PasswordStore on BrowserContextKeyedService
[chromium-blink-merge.git] / chrome / browser / prerender / prerender_field_trial.cc
blob906ed2bb220a0dc245b0383d6b8ad633b93aa238
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.
5 #include "chrome/browser/prerender/prerender_field_trial.h"
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 "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h"
14 #include "chrome/browser/metrics/metrics_service.h"
15 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
16 #include "chrome/browser/prerender/prerender_manager.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/sync/profile_sync_service.h"
19 #include "chrome/browser/sync/profile_sync_service_factory.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/chrome_version_info.h"
22 #include "components/variations/variations_associated_data.h"
24 using base::FieldTrial;
25 using base::FieldTrialList;
26 using base::SplitStringUsingSubstr;
27 using base::StringToInt;
28 using std::string;
29 using std::vector;
31 namespace prerender {
33 namespace {
35 const char kOmniboxTrialName[] = "PrerenderFromOmnibox";
36 int g_omnibox_trial_default_group_number = kint32min;
38 const char kDisabledGroup[] = "Disabled";
39 const char kEnabledGroup[] = "Enabled";
41 const char kLocalPredictorSpecTrialName[] = "PrerenderLocalPredictorSpec";
42 const char kLocalPredictorKeyName[] = "LocalPredictor";
43 const char kLocalPredictorUnencryptedSyncOnlyKeyName[] =
44 "LocalPredictorUnencryptedSyncOnly";
45 const char kSideEffectFreeWhitelistKeyName[] = "SideEffectFreeWhitelist";
46 const char kPrerenderLaunchKeyName[] = "PrerenderLaunch";
47 const char kPrerenderAlwaysControlKeyName[] = "PrerenderAlwaysControl";
48 const char kPrerenderQueryPrerenderServiceKeyName[] =
49 "PrerenderQueryPrerenderService";
50 const char kPrerenderQueryPrerenderServiceCurrentURLKeyName[] =
51 "PrerenderQueryPrerenderServiceCurrentURL";
52 const char kPrerenderQueryPrerenderServiceCandidateURLsKeyName[] =
53 "PrerenderQueryPrerenderServiceCandidateURLs";
54 const char kPrerenderServiceBehaviorIDKeyName[] = "PrerenderServiceBehaviorID";
55 const char kPrerenderServiceFetchTimeoutKeyName[] =
56 "PrerenderServiceFetchTimeoutMs";
57 const char kPrerenderTTLKeyName[] = "PrerenderTTLSeconds";
58 const char kPrerenderPriorityHalfLifeTimeKeyName[] =
59 "PrerenderPriorityHalfLifeTimeSeconds";
60 const char kMaxConcurrentPrerenderKeyName[] = "MaxConcurrentPrerenders";
61 const char kSkipFragment[] = "SkipFragment";
62 const char kSkipHTTPS[] = "SkipHTTPS";
63 const char kSkipWhitelist[] = "SkipWhitelist";
64 const char kSkipServiceWhitelist[] = "SkipServiceWhitelist";
65 const char kSkipLoggedIn[] = "SkipLoggedIn";
66 const char kSkipDefaultNoPrerender[] = "SkipDefaultNoPrerender";
67 const char kPrerenderServiceURLPrefixParameterName[] =
68 "PrerenderServiceURLPrefix";
69 const char kDefaultPrerenderServiceURLPrefix[] =
70 "https://clients4.google.com/prerenderservice/?q=";
71 const int kMinPrerenderServiceTimeoutMs = 1;
72 const int kMaxPrerenderServiceTimeoutMs = 10000;
73 const int kDefaultPrerenderServiceTimeoutMs = 1000;
74 const char kSkipPrerenderLocalCanadidates[] = "SkipPrerenderLocalCandidates";
75 const char kSkipPrerenderServiceCanadidates[] =
76 "SkipPrerenderServiceCandidates";
77 const char kDisableSessionStorageNamespaceMerging[] =
78 "DisableSessionStorageNamespaceMerging";
80 void SetupPrerenderFieldTrial() {
81 const FieldTrial::Probability divisor = 1000;
83 FieldTrial::Probability control_probability;
84 FieldTrial::Probability experiment_multi_prerender_probability;
85 FieldTrial::Probability experiment_15min_ttl_probability;
86 FieldTrial::Probability experiment_no_use_probability;
88 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
89 if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
90 channel == chrome::VersionInfo::CHANNEL_BETA) {
91 // Use very conservatives and stable settings in beta and stable.
92 const FieldTrial::Probability release_prerender_enabled_probability = 980;
93 const FieldTrial::Probability release_control_probability = 10;
94 const FieldTrial::Probability
95 release_experiment_multi_prerender_probability = 0;
96 const FieldTrial::Probability release_experiment_15min_ttl_probability = 10;
97 const FieldTrial::Probability release_experiment_no_use_probability = 0;
98 COMPILE_ASSERT(
99 release_prerender_enabled_probability + release_control_probability +
100 release_experiment_multi_prerender_probability +
101 release_experiment_15min_ttl_probability +
102 release_experiment_no_use_probability == divisor,
103 release_experiment_probabilities_must_equal_divisor);
105 control_probability = release_control_probability;
106 experiment_multi_prerender_probability =
107 release_experiment_multi_prerender_probability;
108 experiment_15min_ttl_probability = release_experiment_15min_ttl_probability;
109 experiment_no_use_probability = release_experiment_no_use_probability;
110 } else {
111 // In testing channels, use more experiments and a larger control group to
112 // improve quality of data.
113 const FieldTrial::Probability dev_prerender_enabled_probability = 250;
114 const FieldTrial::Probability dev_control_probability = 250;
115 const FieldTrial::Probability
116 dev_experiment_multi_prerender_probability = 250;
117 const FieldTrial::Probability dev_experiment_15min_ttl_probability = 125;
118 const FieldTrial::Probability dev_experiment_no_use_probability = 125;
119 COMPILE_ASSERT(dev_prerender_enabled_probability + dev_control_probability +
120 dev_experiment_multi_prerender_probability +
121 dev_experiment_15min_ttl_probability +
122 dev_experiment_no_use_probability == divisor,
123 dev_experiment_probabilities_must_equal_divisor);
125 control_probability = dev_control_probability;
126 experiment_multi_prerender_probability =
127 dev_experiment_multi_prerender_probability;
128 experiment_15min_ttl_probability = dev_experiment_15min_ttl_probability;
129 experiment_no_use_probability = dev_experiment_no_use_probability;
132 int prerender_enabled_group = -1;
133 scoped_refptr<FieldTrial> trial(
134 FieldTrialList::FactoryGetFieldTrial(
135 "Prerender", divisor, "PrerenderEnabled",
136 2014, 12, 31, FieldTrial::SESSION_RANDOMIZED,
137 &prerender_enabled_group));
138 const int control_group =
139 trial->AppendGroup("PrerenderControl",
140 control_probability);
141 const int experiment_multi_prerender_group =
142 trial->AppendGroup("PrerenderMulti",
143 experiment_multi_prerender_probability);
144 const int experiment_15_min_TTL_group =
145 trial->AppendGroup("Prerender15minTTL",
146 experiment_15min_ttl_probability);
147 const int experiment_no_use_group =
148 trial->AppendGroup("PrerenderNoUse",
149 experiment_no_use_probability);
151 const int trial_group = trial->group();
152 if (trial_group == prerender_enabled_group) {
153 PrerenderManager::SetMode(
154 PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP);
155 } else if (trial_group == control_group) {
156 PrerenderManager::SetMode(
157 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
158 } else if (trial_group == experiment_multi_prerender_group) {
159 PrerenderManager::SetMode(
160 PrerenderManager::PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP);
161 } else if (trial_group == experiment_15_min_TTL_group) {
162 PrerenderManager::SetMode(
163 PrerenderManager::PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP);
164 } else if (trial_group == experiment_no_use_group) {
165 PrerenderManager::SetMode(
166 PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP);
167 } else {
168 NOTREACHED();
172 } // end namespace
174 void ConfigureOmniboxPrerender();
176 void ConfigurePrerender(const CommandLine& command_line) {
177 enum PrerenderOption {
178 PRERENDER_OPTION_AUTO,
179 PRERENDER_OPTION_DISABLED,
180 PRERENDER_OPTION_ENABLED,
183 PrerenderOption prerender_option = PRERENDER_OPTION_AUTO;
184 if (command_line.HasSwitch(switches::kPrerenderMode)) {
185 const string switch_value =
186 command_line.GetSwitchValueASCII(switches::kPrerenderMode);
188 if (switch_value == switches::kPrerenderModeSwitchValueAuto) {
189 prerender_option = PRERENDER_OPTION_AUTO;
190 } else if (switch_value == switches::kPrerenderModeSwitchValueDisabled) {
191 prerender_option = PRERENDER_OPTION_DISABLED;
192 } else if (switch_value.empty() ||
193 switch_value == switches::kPrerenderModeSwitchValueEnabled) {
194 // The empty string means the option was provided with no value, and that
195 // means enable.
196 prerender_option = PRERENDER_OPTION_ENABLED;
197 } else {
198 prerender_option = PRERENDER_OPTION_DISABLED;
199 LOG(ERROR) << "Invalid --prerender option received on command line: "
200 << switch_value;
201 LOG(ERROR) << "Disabling prerendering!";
205 switch (prerender_option) {
206 case PRERENDER_OPTION_AUTO:
207 SetupPrerenderFieldTrial();
208 break;
209 case PRERENDER_OPTION_DISABLED:
210 PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
211 break;
212 case PRERENDER_OPTION_ENABLED:
213 PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
214 break;
215 default:
216 NOTREACHED();
219 ConfigureOmniboxPrerender();
222 void ConfigureOmniboxPrerender() {
223 // Field trial to see if we're enabled.
224 const FieldTrial::Probability kDivisor = 100;
226 FieldTrial::Probability kDisabledProbability = 10;
227 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
228 if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
229 channel == chrome::VersionInfo::CHANNEL_BETA) {
230 kDisabledProbability = 1;
232 scoped_refptr<FieldTrial> omnibox_prerender_trial(
233 FieldTrialList::FactoryGetFieldTrial(
234 kOmniboxTrialName, kDivisor, "OmniboxPrerenderEnabled",
235 2014, 12, 31, FieldTrial::SESSION_RANDOMIZED,
236 &g_omnibox_trial_default_group_number));
237 omnibox_prerender_trial->AppendGroup("OmniboxPrerenderDisabled",
238 kDisabledProbability);
241 bool IsOmniboxEnabled(Profile* profile) {
242 if (!profile)
243 return false;
245 if (!PrerenderManager::IsPrerenderingPossible())
246 return false;
248 // Override any field trial groups if the user has set a command line flag.
249 if (CommandLine::ForCurrentProcess()->HasSwitch(
250 switches::kPrerenderFromOmnibox)) {
251 const string switch_value =
252 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
253 switches::kPrerenderFromOmnibox);
255 if (switch_value == switches::kPrerenderFromOmniboxSwitchValueEnabled)
256 return true;
258 if (switch_value == switches::kPrerenderFromOmniboxSwitchValueDisabled)
259 return false;
261 DCHECK(switch_value == switches::kPrerenderFromOmniboxSwitchValueAuto);
264 const int group = FieldTrialList::FindValue(kOmniboxTrialName);
265 return group == FieldTrial::kNotFinalized ||
266 group == g_omnibox_trial_default_group_number;
270 PrerenderLocalPredictorSpec is a field trial, and its value must have the
271 following format:
272 key1=value1:key2=value2:key3=value3
273 eg "LocalPredictor=Enabled:SideEffectFreeWhitelist=Enabled"
274 The function below extracts the value corresponding to a key provided from the
275 LocalPredictorSpec.
277 string GetLocalPredictorSpecValue(string spec_key) {
278 vector<string> elements;
279 SplitStringUsingSubstr(
280 FieldTrialList::FindFullName(kLocalPredictorSpecTrialName),
281 ":",
282 &elements);
283 for (int i = 0; i < static_cast<int>(elements.size()); i++) {
284 vector<string> key_value;
285 SplitStringUsingSubstr(elements[i], "=", &key_value);
286 if (key_value.size() == 2 && key_value[0] == spec_key)
287 return key_value[1];
289 return string();
292 bool IsUnencryptedSyncEnabled(Profile* profile) {
293 ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()->
294 GetForProfile(profile);
295 return service && service->GetOpenTabsUIDelegate() &&
296 !service->EncryptEverythingEnabled();
299 // Indicates whether the Local Predictor is enabled based on field trial
300 // selection.
301 bool IsLocalPredictorEnabled() {
302 #if defined(OS_ANDROID) || defined(OS_IOS)
303 return false;
304 #endif
305 if (CommandLine::ForCurrentProcess()->HasSwitch(
306 switches::kDisablePrerenderLocalPredictor)) {
307 return false;
309 return GetLocalPredictorSpecValue(kLocalPredictorKeyName) == kEnabledGroup;
312 bool DisableLocalPredictorBasedOnSyncAndConfiguration(Profile* profile) {
313 return
314 GetLocalPredictorSpecValue(kLocalPredictorUnencryptedSyncOnlyKeyName) ==
315 kEnabledGroup &&
316 !IsUnencryptedSyncEnabled(profile);
319 bool IsLoggedInPredictorEnabled() {
320 return IsLocalPredictorEnabled();
323 bool IsSideEffectFreeWhitelistEnabled() {
324 return IsLocalPredictorEnabled() &&
325 GetLocalPredictorSpecValue(kSideEffectFreeWhitelistKeyName) !=
326 kDisabledGroup;
329 bool IsLocalPredictorPrerenderLaunchEnabled() {
330 return GetLocalPredictorSpecValue(kPrerenderLaunchKeyName) != kDisabledGroup;
333 bool IsLocalPredictorPrerenderAlwaysControlEnabled() {
334 return GetLocalPredictorSpecValue(kPrerenderAlwaysControlKeyName) ==
335 kEnabledGroup;
338 bool ShouldQueryPrerenderService(Profile* profile) {
339 return IsUnencryptedSyncEnabled(profile) &&
340 GetLocalPredictorSpecValue(kPrerenderQueryPrerenderServiceKeyName) ==
341 kEnabledGroup;
344 bool ShouldQueryPrerenderServiceForCurrentURL() {
345 return GetLocalPredictorSpecValue(
346 kPrerenderQueryPrerenderServiceCurrentURLKeyName) != kDisabledGroup;
349 bool ShouldQueryPrerenderServiceForCandidateURLs() {
350 return GetLocalPredictorSpecValue(
351 kPrerenderQueryPrerenderServiceCandidateURLsKeyName) != kDisabledGroup;
354 string GetPrerenderServiceURLPrefix() {
355 string prefix = chrome_variations::GetVariationParamValue(
356 kLocalPredictorSpecTrialName,
357 kPrerenderServiceURLPrefixParameterName);
358 if (prefix.empty())
359 prefix = kDefaultPrerenderServiceURLPrefix;
360 return prefix;
363 int GetPrerenderServiceBehaviorID() {
364 int id;
365 StringToInt(GetLocalPredictorSpecValue(kPrerenderServiceBehaviorIDKeyName),
366 &id);
367 // The behavior ID must be non-negative.
368 if (id < 0)
369 id = 0;
370 return id;
373 int GetPrerenderServiceFetchTimeoutMs() {
374 int result;
375 StringToInt(GetLocalPredictorSpecValue(kPrerenderServiceFetchTimeoutKeyName),
376 &result);
377 // The behavior ID must be non-negative.
378 if (result < kMinPrerenderServiceTimeoutMs ||
379 result > kMaxPrerenderServiceTimeoutMs) {
380 result = kDefaultPrerenderServiceTimeoutMs;
382 return result;
385 int GetLocalPredictorTTLSeconds() {
386 int ttl;
387 StringToInt(GetLocalPredictorSpecValue(kPrerenderTTLKeyName), &ttl);
388 // If the value is outside of 10s or 600s, use a default value of 180s.
389 if (ttl < 10 || ttl > 600)
390 ttl = 180;
391 return ttl;
394 int GetLocalPredictorPrerenderPriorityHalfLifeTimeSeconds() {
395 int half_life_time;
396 StringToInt(GetLocalPredictorSpecValue(kPrerenderPriorityHalfLifeTimeKeyName),
397 &half_life_time);
398 // Sanity check: Ensure the half life time is non-negative.
399 if (half_life_time < 0)
400 half_life_time = 0;
401 return half_life_time;
404 int GetLocalPredictorMaxConcurrentPrerenders() {
405 int num_prerenders;
406 StringToInt(GetLocalPredictorSpecValue(kMaxConcurrentPrerenderKeyName),
407 &num_prerenders);
408 // Sanity check: Ensure the number of prerenders is at least 1.
409 if (num_prerenders < 1)
410 num_prerenders = 1;
411 // Sanity check: Ensure the number of prerenders is at most 10.
412 if (num_prerenders > 10)
413 num_prerenders = 10;
414 return num_prerenders;
417 bool SkipLocalPredictorFragment() {
418 return GetLocalPredictorSpecValue(kSkipFragment) == kEnabledGroup;
421 bool SkipLocalPredictorHTTPS() {
422 return GetLocalPredictorSpecValue(kSkipHTTPS) == kEnabledGroup;
425 bool SkipLocalPredictorWhitelist() {
426 return GetLocalPredictorSpecValue(kSkipWhitelist) == kEnabledGroup;
429 bool SkipLocalPredictorServiceWhitelist() {
430 return GetLocalPredictorSpecValue(kSkipServiceWhitelist) == kEnabledGroup;
433 bool SkipLocalPredictorLoggedIn() {
434 return GetLocalPredictorSpecValue(kSkipLoggedIn) == kEnabledGroup;
437 bool SkipLocalPredictorDefaultNoPrerender() {
438 return GetLocalPredictorSpecValue(kSkipDefaultNoPrerender) == kEnabledGroup;
441 bool SkipLocalPredictorLocalCandidates() {
442 return GetLocalPredictorSpecValue(kSkipPrerenderLocalCanadidates) ==
443 kEnabledGroup;
446 bool SkipLocalPredictorServiceCandidates() {
447 return GetLocalPredictorSpecValue(kSkipPrerenderServiceCanadidates) ==
448 kEnabledGroup;
451 bool ShouldMergeSessionStorageNamespaces() {
452 return GetLocalPredictorSpecValue(kDisableSessionStorageNamespaceMerging) !=
453 kDisabledGroup;
456 } // namespace prerender