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 "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h"
14 #include "chrome/browser/net/prediction_options.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 "chrome/common/pref_names.h"
23 #include "components/metrics/metrics_service.h"
24 #include "components/variations/variations_associated_data.h"
25
26 using base::FieldTrial;
27 using base::FieldTrialList;
28 using base::StringToInt;
29 using std::string;
30 using std::vector;
31
32 namespace prerender {
33
34 namespace {
35
36 const char kOmniboxTrialName[] = "PrerenderFromOmnibox";
37 int g_omnibox_trial_default_group_number = kint32min;
38
39 const char kDisabledGroup[] = "Disabled";
40 const char kEnabledGroup[] = "Enabled";
41
42 const char kLocalPredictorSpecTrialName[] = "PrerenderLocalPredictorSpec";
43 const char kLocalPredictorKeyName[] = "LocalPredictor";
44 const char kLocalPredictorUnencryptedSyncOnlyKeyName[] =
45 "LocalPredictorUnencryptedSyncOnly";
46 const char kLocalPredictorNetworkPredictionEnabledOnly[] =
47 "LocalPredictorNetworkPredictionEnabledOnly";
48 const char kLocalPredictorOnCellularOnly[] = "LocalPredictorOnCellularOnly";
49 const char kSideEffectFreeWhitelistKeyName[] = "SideEffectFreeWhitelist";
50 const char kPrerenderLaunchKeyName[] = "PrerenderLaunch";
51 const char kPrerenderAlwaysControlKeyName[] = "PrerenderAlwaysControl";
52 const char kPrerenderPrefetchKeyName[] = "PrerenderPrefetch";
53 const char kPrerenderQueryPrerenderServiceKeyName[] =
54 "PrerenderQueryPrerenderService";
55 const char kPrerenderQueryPrerenderServiceCurrentURLKeyName[] =
56 "PrerenderQueryPrerenderServiceCurrentURL";
57 const char kPrerenderQueryPrerenderServiceCandidateURLsKeyName[] =
58 "PrerenderQueryPrerenderServiceCandidateURLs";
59 const char kPrerenderServiceBehaviorIDKeyName[] = "PrerenderServiceBehaviorID";
60 const char kPrerenderServiceFetchTimeoutKeyName[] =
61 "PrerenderServiceFetchTimeoutMs";
62 const char kPrefetchListTimeoutKeyName[] = "PrefetchListTimeoutSeconds";
63 const char kPrerenderTTLKeyName[] = "PrerenderTTLSeconds";
64 const char kPrerenderPriorityHalfLifeTimeKeyName[] =
65 "PrerenderPriorityHalfLifeTimeSeconds";
66 const char kMaxConcurrentPrerenderKeyName[] = "MaxConcurrentPrerenders";
67 const char kMaxLaunchPrerenderKeyName[] = "MaxLaunchPrerenders";
68 const char kSkipFragment[] = "SkipFragment";
69 const char kSkipHTTPS[] = "SkipHTTPS";
70 const char kSkipWhitelist[] = "SkipWhitelist";
71 const char kSkipServiceWhitelist[] = "SkipServiceWhitelist";
72 const char kSkipLoggedIn[] = "SkipLoggedIn";
73 const char kSkipDefaultNoPrerender[] = "SkipDefaultNoPrerender";
74 const char kPrerenderServiceURLPrefixParameterName[] =
75 "PrerenderServiceURLPrefix";
76 const char kDefaultPrerenderServiceURLPrefix[] =
77 "https://clients4.google.com/prerenderservice/?q=";
78 const int kMinPrerenderServiceTimeoutMs = 1;
79 const int kMaxPrerenderServiceTimeoutMs = 10000;
80 const int kDefaultPrerenderServiceTimeoutMs = 1000;
81 const int kMinPrefetchListTimeoutSeconds = 1;
82 const int kMaxPrefetchListTimeoutSeconds = 1800;
83 const int kDefaultPrefetchListTimeoutSeconds = 300;
84 const char kSkipPrerenderLocalCanadidates[] = "SkipPrerenderLocalCandidates";
85 const char kSkipPrerenderServiceCanadidates[] =
86 "SkipPrerenderServiceCandidates";
87 const char kDisableSessionStorageNamespaceMerging[] =
88 "DisableSessionStorageNamespaceMerging";
89 const char kPrerenderCookieStore[] = "PrerenderCookieStore";
90
SetupPrerenderFieldTrial()91 void SetupPrerenderFieldTrial() {
92 const FieldTrial::Probability divisor = 1000;
93
94 FieldTrial::Probability control_probability;
95 FieldTrial::Probability experiment_multi_prerender_probability;
96 FieldTrial::Probability experiment_15min_ttl_probability;
97 FieldTrial::Probability experiment_no_use_probability;
98 FieldTrial::Probability experiment_match_complete_probability;
99
100 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
101 if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
102 channel == chrome::VersionInfo::CHANNEL_BETA) {
103 // Use very conservatives and stable settings in beta and stable.
104 const FieldTrial::Probability release_prerender_enabled_probability = 970;
105 const FieldTrial::Probability release_control_probability = 10;
106 const FieldTrial::Probability
107 release_experiment_multi_prerender_probability = 0;
108 const FieldTrial::Probability release_experiment_15min_ttl_probability = 10;
109 const FieldTrial::Probability release_experiment_no_use_probability = 0;
110 const FieldTrial::Probability
111 release_experiment_match_complete_probability = 10;
112 COMPILE_ASSERT(
113 release_prerender_enabled_probability +
114 release_control_probability +
115 release_experiment_multi_prerender_probability +
116 release_experiment_15min_ttl_probability +
117 release_experiment_no_use_probability +
118 release_experiment_match_complete_probability == divisor,
119 release_experiment_probabilities_must_equal_divisor);
120
121 control_probability = release_control_probability;
122 experiment_multi_prerender_probability =
123 release_experiment_multi_prerender_probability;
124 experiment_15min_ttl_probability = release_experiment_15min_ttl_probability;
125 experiment_no_use_probability = release_experiment_no_use_probability;
126 experiment_match_complete_probability =
127 release_experiment_match_complete_probability;
128 } else {
129 // In testing channels, use more experiments and a larger control group to
130 // improve quality of data.
131 const FieldTrial::Probability dev_prerender_enabled_probability = 200;
132 const FieldTrial::Probability dev_control_probability = 200;
133 const FieldTrial::Probability
134 dev_experiment_multi_prerender_probability = 200;
135 const FieldTrial::Probability dev_experiment_15min_ttl_probability = 100;
136 const FieldTrial::Probability dev_experiment_no_use_probability = 100;
137 const FieldTrial::Probability
138 dev_experiment_match_complete_probability = 200;
139 COMPILE_ASSERT(dev_prerender_enabled_probability +
140 dev_control_probability +
141 dev_experiment_multi_prerender_probability +
142 dev_experiment_15min_ttl_probability +
143 dev_experiment_no_use_probability +
144 dev_experiment_match_complete_probability == divisor,
145 dev_experiment_probabilities_must_equal_divisor);
146
147 control_probability = dev_control_probability;
148 experiment_multi_prerender_probability =
149 dev_experiment_multi_prerender_probability;
150 experiment_15min_ttl_probability = dev_experiment_15min_ttl_probability;
151 experiment_no_use_probability = dev_experiment_no_use_probability;
152 experiment_match_complete_probability =
153 dev_experiment_match_complete_probability;
154 }
155
156 int prerender_enabled_group = -1;
157 scoped_refptr<FieldTrial> trial(
158 FieldTrialList::FactoryGetFieldTrial(
159 "Prerender", divisor, "PrerenderEnabled",
160 2014, 12, 31, FieldTrial::SESSION_RANDOMIZED,
161 &prerender_enabled_group));
162 const int control_group =
163 trial->AppendGroup("PrerenderControl",
164 control_probability);
165 const int experiment_multi_prerender_group =
166 trial->AppendGroup("PrerenderMulti",
167 experiment_multi_prerender_probability);
168 const int experiment_15_min_TTL_group =
169 trial->AppendGroup("Prerender15minTTL",
170 experiment_15min_ttl_probability);
171 const int experiment_no_use_group =
172 trial->AppendGroup("PrerenderNoUse",
173 experiment_no_use_probability);
174 const int experiment_match_complete_group =
175 trial->AppendGroup("MatchComplete",
176 experiment_match_complete_probability);
177
178 const int trial_group = trial->group();
179 if (trial_group == prerender_enabled_group) {
180 PrerenderManager::SetMode(
181 PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP);
182 } else if (trial_group == control_group) {
183 PrerenderManager::SetMode(
184 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
185 } else if (trial_group == experiment_multi_prerender_group) {
186 PrerenderManager::SetMode(
187 PrerenderManager::PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP);
188 } else if (trial_group == experiment_15_min_TTL_group) {
189 PrerenderManager::SetMode(
190 PrerenderManager::PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP);
191 } else if (trial_group == experiment_no_use_group) {
192 PrerenderManager::SetMode(
193 PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP);
194 } else if (trial_group == experiment_match_complete_group) {
195 PrerenderManager::SetMode(
196 PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
197 } else {
198 NOTREACHED();
199 }
200 }
201
202 } // end namespace
203
204 void ConfigureOmniboxPrerender();
205
ConfigurePrerender(const CommandLine & command_line)206 void ConfigurePrerender(const CommandLine& command_line) {
207 enum PrerenderOption {
208 PRERENDER_OPTION_AUTO,
209 PRERENDER_OPTION_DISABLED,
210 PRERENDER_OPTION_ENABLED,
211 };
212
213 PrerenderOption prerender_option = PRERENDER_OPTION_AUTO;
214 if (command_line.HasSwitch(switches::kPrerenderMode)) {
215 const string switch_value =
216 command_line.GetSwitchValueASCII(switches::kPrerenderMode);
217
218 if (switch_value == switches::kPrerenderModeSwitchValueAuto) {
219 prerender_option = PRERENDER_OPTION_AUTO;
220 } else if (switch_value == switches::kPrerenderModeSwitchValueDisabled) {
221 prerender_option = PRERENDER_OPTION_DISABLED;
222 } else if (switch_value.empty() ||
223 switch_value == switches::kPrerenderModeSwitchValueEnabled) {
224 // The empty string means the option was provided with no value, and that
225 // means enable.
226 prerender_option = PRERENDER_OPTION_ENABLED;
227 } else {
228 prerender_option = PRERENDER_OPTION_DISABLED;
229 LOG(ERROR) << "Invalid --prerender option received on command line: "
230 << switch_value;
231 LOG(ERROR) << "Disabling prerendering!";
232 }
233 }
234
235 switch (prerender_option) {
236 case PRERENDER_OPTION_AUTO:
237 SetupPrerenderFieldTrial();
238 break;
239 case PRERENDER_OPTION_DISABLED:
240 PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
241 break;
242 case PRERENDER_OPTION_ENABLED:
243 PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
244 break;
245 default:
246 NOTREACHED();
247 }
248
249 ConfigureOmniboxPrerender();
250 }
251
ConfigureOmniboxPrerender()252 void ConfigureOmniboxPrerender() {
253 // Field trial to see if we're enabled.
254 const FieldTrial::Probability kDivisor = 100;
255
256 FieldTrial::Probability kDisabledProbability = 10;
257 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
258 if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
259 channel == chrome::VersionInfo::CHANNEL_BETA) {
260 kDisabledProbability = 1;
261 }
262 scoped_refptr<FieldTrial> omnibox_prerender_trial(
263 FieldTrialList::FactoryGetFieldTrial(
264 kOmniboxTrialName, kDivisor, "OmniboxPrerenderEnabled",
265 2014, 12, 31, FieldTrial::SESSION_RANDOMIZED,
266 &g_omnibox_trial_default_group_number));
267 omnibox_prerender_trial->AppendGroup("OmniboxPrerenderDisabled",
268 kDisabledProbability);
269 }
270
IsOmniboxEnabled(Profile * profile)271 bool IsOmniboxEnabled(Profile* profile) {
272 if (!profile)
273 return false;
274
275 if (!PrerenderManager::IsPrerenderingPossible())
276 return false;
277
278 // Override any field trial groups if the user has set a command line flag.
279 if (CommandLine::ForCurrentProcess()->HasSwitch(
280 switches::kPrerenderFromOmnibox)) {
281 const string switch_value =
282 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
283 switches::kPrerenderFromOmnibox);
284
285 if (switch_value == switches::kPrerenderFromOmniboxSwitchValueEnabled)
286 return true;
287
288 if (switch_value == switches::kPrerenderFromOmniboxSwitchValueDisabled)
289 return false;
290
291 DCHECK_EQ(switches::kPrerenderFromOmniboxSwitchValueAuto, switch_value);
292 }
293
294 const int group = FieldTrialList::FindValue(kOmniboxTrialName);
295 return group == FieldTrial::kNotFinalized ||
296 group == g_omnibox_trial_default_group_number;
297 }
298
299 /*
300 PrerenderLocalPredictorSpec is a field trial, and its value must have the
301 following format:
302 key1=value1:key2=value2:key3=value3
303 eg "LocalPredictor=Enabled:SideEffectFreeWhitelist=Enabled"
304 The function below extracts the value corresponding to a key provided from the
305 LocalPredictorSpec.
306 */
GetLocalPredictorSpecValue(string spec_key)307 string GetLocalPredictorSpecValue(string spec_key) {
308 vector<string> elements;
309 base::SplitString(FieldTrialList::FindFullName(kLocalPredictorSpecTrialName),
310 ':', &elements);
311 for (int i = 0; i < static_cast<int>(elements.size()); i++) {
312 vector<string> key_value;
313 base::SplitString(elements[i], '=', &key_value);
314 if (key_value.size() == 2 && key_value[0] == spec_key)
315 return key_value[1];
316 }
317 return string();
318 }
319
IsUnencryptedSyncEnabled(Profile * profile)320 bool IsUnencryptedSyncEnabled(Profile* profile) {
321 ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()->
322 GetForProfile(profile);
323 return service && service->GetOpenTabsUIDelegate() &&
324 !service->EncryptEverythingEnabled();
325 }
326
327 // Indicates whether the Local Predictor is enabled based on field trial
328 // selection.
IsLocalPredictorEnabled()329 bool IsLocalPredictorEnabled() {
330 #if defined(OS_ANDROID) || defined(OS_IOS)
331 return false;
332 #endif
333 return
334 !CommandLine::ForCurrentProcess()->HasSwitch(
335 switches::kDisablePrerenderLocalPredictor) &&
336 GetLocalPredictorSpecValue(kLocalPredictorKeyName) == kEnabledGroup;
337 }
338
ShouldDisableLocalPredictorBasedOnSyncAndConfiguration(Profile * profile)339 bool ShouldDisableLocalPredictorBasedOnSyncAndConfiguration(Profile* profile) {
340 return
341 GetLocalPredictorSpecValue(kLocalPredictorUnencryptedSyncOnlyKeyName) ==
342 kEnabledGroup &&
343 !IsUnencryptedSyncEnabled(profile);
344 }
345
ShouldDisableLocalPredictorDueToPreferencesAndNetwork(Profile * profile)346 bool ShouldDisableLocalPredictorDueToPreferencesAndNetwork(Profile* profile) {
347 bool on_cellular =
348 net::NetworkChangeNotifier::IsConnectionCellular(
349 net::NetworkChangeNotifier::GetConnectionType());
350 // If the user is not on a cellular connection, but we require a cellular
351 // connection, we must temporarily disable our local predictions.
352 if (!on_cellular &&
353 GetLocalPredictorSpecValue(kLocalPredictorOnCellularOnly) ==
354 kEnabledGroup) {
355 return true;
356 }
357
358 // If we don't care whether or not network prediction will actually be
359 // exercised, we do not need to temporarily disable our predictions.
360 if (GetLocalPredictorSpecValue(kLocalPredictorNetworkPredictionEnabledOnly) !=
361 kEnabledGroup) {
362 return false;
363 }
364
365 // We should temporarily disable iff the predictive network action would
366 // not be exercised.
367
368 return !chrome_browser_net::CanPrefetchAndPrerenderUI(profile->GetPrefs());
369 }
370
IsLoggedInPredictorEnabled()371 bool IsLoggedInPredictorEnabled() {
372 return IsLocalPredictorEnabled();
373 }
374
IsSideEffectFreeWhitelistEnabled()375 bool IsSideEffectFreeWhitelistEnabled() {
376 return IsLocalPredictorEnabled() &&
377 GetLocalPredictorSpecValue(kSideEffectFreeWhitelistKeyName) !=
378 kDisabledGroup;
379 }
380
IsLocalPredictorPrerenderLaunchEnabled()381 bool IsLocalPredictorPrerenderLaunchEnabled() {
382 return GetLocalPredictorSpecValue(kPrerenderLaunchKeyName) != kDisabledGroup;
383 }
384
IsLocalPredictorPrerenderAlwaysControlEnabled()385 bool IsLocalPredictorPrerenderAlwaysControlEnabled() {
386 // If we prefetch rather than prerender, we automatically also prerender
387 // as a control group only.
388 return (GetLocalPredictorSpecValue(kPrerenderAlwaysControlKeyName) ==
389 kEnabledGroup) || IsLocalPredictorPrerenderPrefetchEnabled();
390 }
391
IsLocalPredictorPrerenderPrefetchEnabled()392 bool IsLocalPredictorPrerenderPrefetchEnabled() {
393 return GetLocalPredictorSpecValue(kPrerenderPrefetchKeyName) ==
394 kEnabledGroup;
395 }
396
ShouldQueryPrerenderService(Profile * profile)397 bool ShouldQueryPrerenderService(Profile* profile) {
398 return IsUnencryptedSyncEnabled(profile) &&
399 GetLocalPredictorSpecValue(kPrerenderQueryPrerenderServiceKeyName) ==
400 kEnabledGroup;
401 }
402
ShouldQueryPrerenderServiceForCurrentURL()403 bool ShouldQueryPrerenderServiceForCurrentURL() {
404 return GetLocalPredictorSpecValue(
405 kPrerenderQueryPrerenderServiceCurrentURLKeyName) != kDisabledGroup;
406 }
407
ShouldQueryPrerenderServiceForCandidateURLs()408 bool ShouldQueryPrerenderServiceForCandidateURLs() {
409 return GetLocalPredictorSpecValue(
410 kPrerenderQueryPrerenderServiceCandidateURLsKeyName) != kDisabledGroup;
411 }
412
GetPrerenderServiceURLPrefix()413 string GetPrerenderServiceURLPrefix() {
414 string prefix = variations::GetVariationParamValue(
415 kLocalPredictorSpecTrialName,
416 kPrerenderServiceURLPrefixParameterName);
417 return prefix.empty() ? kDefaultPrerenderServiceURLPrefix : prefix;
418 }
419
GetPrerenderServiceBehaviorID()420 int GetPrerenderServiceBehaviorID() {
421 int id;
422 StringToInt(GetLocalPredictorSpecValue(kPrerenderServiceBehaviorIDKeyName),
423 &id);
424 // The behavior ID must be non-negative.
425 return std::max(id, 0);
426 }
427
GetPrerenderServiceFetchTimeoutMs()428 int GetPrerenderServiceFetchTimeoutMs() {
429 int result;
430 StringToInt(GetLocalPredictorSpecValue(kPrerenderServiceFetchTimeoutKeyName),
431 &result);
432 // If the value is outside the valid range, use the default value.
433 return (result < kMinPrerenderServiceTimeoutMs ||
434 result > kMaxPrerenderServiceTimeoutMs) ?
435 kDefaultPrerenderServiceTimeoutMs : result;
436 }
437
GetPrerenderPrefetchListTimeoutSeconds()438 int GetPrerenderPrefetchListTimeoutSeconds() {
439 int result;
440 StringToInt(GetLocalPredictorSpecValue(kPrefetchListTimeoutKeyName), &result);
441 // If the value is outside the valid range, use the default value.
442 return (result < kMinPrefetchListTimeoutSeconds ||
443 result > kMaxPrefetchListTimeoutSeconds) ?
444 kDefaultPrefetchListTimeoutSeconds : result;
445 }
446
GetLocalPredictorTTLSeconds()447 int GetLocalPredictorTTLSeconds() {
448 int ttl;
449 StringToInt(GetLocalPredictorSpecValue(kPrerenderTTLKeyName), &ttl);
450 // If the value is outside of 10s or 600s, use a default value of 180s.
451 return (ttl < 10 || ttl > 600) ? 180 : ttl;
452 }
453
GetLocalPredictorPrerenderPriorityHalfLifeTimeSeconds()454 int GetLocalPredictorPrerenderPriorityHalfLifeTimeSeconds() {
455 int half_life_time;
456 StringToInt(GetLocalPredictorSpecValue(kPrerenderPriorityHalfLifeTimeKeyName),
457 &half_life_time);
458 // Sanity check: Ensure the half life time is non-negative.
459 return std::max(half_life_time, 0);
460 }
461
GetLocalPredictorMaxConcurrentPrerenders()462 int GetLocalPredictorMaxConcurrentPrerenders() {
463 int num_prerenders;
464 StringToInt(GetLocalPredictorSpecValue(kMaxConcurrentPrerenderKeyName),
465 &num_prerenders);
466 // Sanity check: Ensure the number of prerenders is between 1 and 10.
467 return std::min(std::max(num_prerenders, 1), 10);
468 }
469
GetLocalPredictorMaxLaunchPrerenders()470 int GetLocalPredictorMaxLaunchPrerenders() {
471 int num_prerenders;
472 StringToInt(GetLocalPredictorSpecValue(kMaxLaunchPrerenderKeyName),
473 &num_prerenders);
474 // Sanity check: Ensure the number of prerenders is between 1 and 10.
475 return std::min(std::max(num_prerenders, 1), 10);
476 }
477
SkipLocalPredictorFragment()478 bool SkipLocalPredictorFragment() {
479 return GetLocalPredictorSpecValue(kSkipFragment) == kEnabledGroup;
480 }
481
SkipLocalPredictorHTTPS()482 bool SkipLocalPredictorHTTPS() {
483 return GetLocalPredictorSpecValue(kSkipHTTPS) == kEnabledGroup;
484 }
485
SkipLocalPredictorWhitelist()486 bool SkipLocalPredictorWhitelist() {
487 return GetLocalPredictorSpecValue(kSkipWhitelist) == kEnabledGroup;
488 }
489
SkipLocalPredictorServiceWhitelist()490 bool SkipLocalPredictorServiceWhitelist() {
491 return GetLocalPredictorSpecValue(kSkipServiceWhitelist) == kEnabledGroup;
492 }
493
SkipLocalPredictorLoggedIn()494 bool SkipLocalPredictorLoggedIn() {
495 return GetLocalPredictorSpecValue(kSkipLoggedIn) == kEnabledGroup;
496 }
497
SkipLocalPredictorDefaultNoPrerender()498 bool SkipLocalPredictorDefaultNoPrerender() {
499 return GetLocalPredictorSpecValue(kSkipDefaultNoPrerender) == kEnabledGroup;
500 }
501
SkipLocalPredictorLocalCandidates()502 bool SkipLocalPredictorLocalCandidates() {
503 return GetLocalPredictorSpecValue(kSkipPrerenderLocalCanadidates) ==
504 kEnabledGroup;
505 }
506
SkipLocalPredictorServiceCandidates()507 bool SkipLocalPredictorServiceCandidates() {
508 return GetLocalPredictorSpecValue(kSkipPrerenderServiceCanadidates) ==
509 kEnabledGroup;
510 }
511
ShouldMergeSessionStorageNamespaces()512 bool ShouldMergeSessionStorageNamespaces() {
513 return GetLocalPredictorSpecValue(kDisableSessionStorageNamespaceMerging) !=
514 kDisabledGroup;
515 }
516
IsPrerenderCookieStoreEnabled()517 bool IsPrerenderCookieStoreEnabled() {
518 return GetLocalPredictorSpecValue(kPrerenderCookieStore) != kDisabledGroup &&
519 FieldTrialList::FindFullName(kPrerenderCookieStore) != kDisabledGroup;
520 }
521
522 } // namespace prerender
523