Home | History | Annotate | Download | only in prerender
      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 
     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 
    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 
    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 
    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 */
    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 
    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.
    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 
    339 bool ShouldDisableLocalPredictorBasedOnSyncAndConfiguration(Profile* profile) {
    340   return
    341       GetLocalPredictorSpecValue(kLocalPredictorUnencryptedSyncOnlyKeyName) ==
    342           kEnabledGroup &&
    343       !IsUnencryptedSyncEnabled(profile);
    344 }
    345 
    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 
    371 bool IsLoggedInPredictorEnabled() {
    372   return IsLocalPredictorEnabled();
    373 }
    374 
    375 bool IsSideEffectFreeWhitelistEnabled() {
    376   return IsLocalPredictorEnabled() &&
    377       GetLocalPredictorSpecValue(kSideEffectFreeWhitelistKeyName) !=
    378       kDisabledGroup;
    379 }
    380 
    381 bool IsLocalPredictorPrerenderLaunchEnabled() {
    382   return GetLocalPredictorSpecValue(kPrerenderLaunchKeyName) != kDisabledGroup;
    383 }
    384 
    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 
    392 bool IsLocalPredictorPrerenderPrefetchEnabled() {
    393   return GetLocalPredictorSpecValue(kPrerenderPrefetchKeyName) ==
    394       kEnabledGroup;
    395 }
    396 
    397 bool ShouldQueryPrerenderService(Profile* profile) {
    398   return IsUnencryptedSyncEnabled(profile) &&
    399       GetLocalPredictorSpecValue(kPrerenderQueryPrerenderServiceKeyName) ==
    400       kEnabledGroup;
    401 }
    402 
    403 bool ShouldQueryPrerenderServiceForCurrentURL() {
    404   return GetLocalPredictorSpecValue(
    405       kPrerenderQueryPrerenderServiceCurrentURLKeyName) != kDisabledGroup;
    406 }
    407 
    408 bool ShouldQueryPrerenderServiceForCandidateURLs() {
    409   return GetLocalPredictorSpecValue(
    410       kPrerenderQueryPrerenderServiceCandidateURLsKeyName) != kDisabledGroup;
    411 }
    412 
    413 string GetPrerenderServiceURLPrefix() {
    414   string prefix = variations::GetVariationParamValue(
    415       kLocalPredictorSpecTrialName,
    416       kPrerenderServiceURLPrefixParameterName);
    417   return prefix.empty() ? kDefaultPrerenderServiceURLPrefix : prefix;
    418 }
    419 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    478 bool SkipLocalPredictorFragment() {
    479   return GetLocalPredictorSpecValue(kSkipFragment) == kEnabledGroup;
    480 }
    481 
    482 bool SkipLocalPredictorHTTPS() {
    483   return GetLocalPredictorSpecValue(kSkipHTTPS) == kEnabledGroup;
    484 }
    485 
    486 bool SkipLocalPredictorWhitelist() {
    487   return GetLocalPredictorSpecValue(kSkipWhitelist) == kEnabledGroup;
    488 }
    489 
    490 bool SkipLocalPredictorServiceWhitelist() {
    491   return GetLocalPredictorSpecValue(kSkipServiceWhitelist) == kEnabledGroup;
    492 }
    493 
    494 bool SkipLocalPredictorLoggedIn() {
    495   return GetLocalPredictorSpecValue(kSkipLoggedIn) == kEnabledGroup;
    496 }
    497 
    498 bool SkipLocalPredictorDefaultNoPrerender() {
    499   return GetLocalPredictorSpecValue(kSkipDefaultNoPrerender) == kEnabledGroup;
    500 }
    501 
    502 bool SkipLocalPredictorLocalCandidates() {
    503   return GetLocalPredictorSpecValue(kSkipPrerenderLocalCanadidates) ==
    504       kEnabledGroup;
    505 }
    506 
    507 bool SkipLocalPredictorServiceCandidates() {
    508   return GetLocalPredictorSpecValue(kSkipPrerenderServiceCanadidates) ==
    509       kEnabledGroup;
    510 }
    511 
    512 bool ShouldMergeSessionStorageNamespaces() {
    513   return GetLocalPredictorSpecValue(kDisableSessionStorageNamespaceMerging) !=
    514       kDisabledGroup;
    515 }
    516 
    517 bool IsPrerenderCookieStoreEnabled() {
    518   return GetLocalPredictorSpecValue(kPrerenderCookieStore) != kDisabledGroup &&
    519       FieldTrialList::FindFullName(kPrerenderCookieStore) != kDisabledGroup;
    520 }
    521 
    522 }  // namespace prerender
    523