| Index: base/metrics/field_trial.cc
 | 
| diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
 | 
| index f11ef3535364ea609421842b99504373d36e0b52..505bba243724fa092feeaa6ce7fcbe787cfecfcf 100644
 | 
| --- a/base/metrics/field_trial.cc
 | 
| +++ b/base/metrics/field_trial.cc
 | 
| @@ -10,7 +10,6 @@
 | 
|  #include "base/base_switches.h"
 | 
|  #include "base/build_time.h"
 | 
|  #include "base/command_line.h"
 | 
| -#include "base/feature_list.h"
 | 
|  #include "base/logging.h"
 | 
|  #include "base/metrics/field_trial_param_associator.h"
 | 
|  #include "base/pickle.h"
 | 
| @@ -49,6 +48,10 @@ const char kActivationMarker = '*';
 | 
|  // for now while the implementation is fleshed out (e.g. data format, single
 | 
|  // shared memory segment). See https://codereview.chromium.org/2365273004/ and
 | 
|  // crbug.com/653874
 | 
| +// The browser is the only process that has write access to the shared memory.
 | 
| +// This is safe from race conditions because MakeIterable is a release operation
 | 
| +// and GetNextOfType is an acquire operation, so memory writes before
 | 
| +// MakeIterable happen before memory reads after GetNextOfType.
 | 
|  const bool kUseSharedMemoryForFieldTrials = true;
 | 
|  
 | 
|  // Constants for the field trial allocator.
 | 
| @@ -248,7 +251,19 @@ bool ParseFieldTrialsString(const std::string& trials_string,
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| -void AddForceFieldTrialsFlag(CommandLine* cmd_line) {
 | 
| +void AddFeatureAndFieldTrialFlags(const char* enable_features_switch,
 | 
| +                                  const char* disable_features_switch,
 | 
| +                                  CommandLine* cmd_line) {
 | 
| +  std::string enabled_features;
 | 
| +  std::string disabled_features;
 | 
| +  FeatureList::GetInstance()->GetFeatureOverrides(&enabled_features,
 | 
| +                                                  &disabled_features);
 | 
| +
 | 
| +  if (!enabled_features.empty())
 | 
| +    cmd_line->AppendSwitchASCII(enable_features_switch, enabled_features);
 | 
| +  if (!disabled_features.empty())
 | 
| +    cmd_line->AppendSwitchASCII(disable_features_switch, disabled_features);
 | 
| +
 | 
|    std::string field_trial_states;
 | 
|    FieldTrialList::AllStatesToString(&field_trial_states);
 | 
|    if (!field_trial_states.empty()) {
 | 
| @@ -805,6 +820,24 @@ void FieldTrialList::CreateTrialsFromCommandLine(
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +// static
 | 
| +void FieldTrialList::CreateFeaturesFromCommandLine(
 | 
| +    const base::CommandLine& command_line,
 | 
| +    const char* enable_features_switch,
 | 
| +    const char* disable_features_switch,
 | 
| +    FeatureList* feature_list) {
 | 
| +  // Fallback to command line if not using shared memory.
 | 
| +  if (!kUseSharedMemoryForFieldTrials ||
 | 
| +      !global_->field_trial_allocator_.get()) {
 | 
| +    return feature_list->InitializeFromCommandLine(
 | 
| +        command_line.GetSwitchValueASCII(enable_features_switch),
 | 
| +        command_line.GetSwitchValueASCII(disable_features_switch));
 | 
| +  }
 | 
| +
 | 
| +  feature_list->InitializeFromSharedMemory(
 | 
| +      global_->field_trial_allocator_.get());
 | 
| +}
 | 
| +
 | 
|  #if defined(POSIX_WITH_ZYGOTE)
 | 
|  // static
 | 
|  bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) {
 | 
| @@ -854,12 +887,19 @@ int FieldTrialList::GetFieldTrialHandle() {
 | 
|  // static
 | 
|  void FieldTrialList::CopyFieldTrialStateToFlags(
 | 
|      const char* field_trial_handle_switch,
 | 
| +    const char* enable_features_switch,
 | 
| +    const char* disable_features_switch,
 | 
|      CommandLine* cmd_line) {
 | 
|    // TODO(lawrencewu): Ideally, having the global would be guaranteed. However,
 | 
|    // content browser tests currently don't create a FieldTrialList because they
 | 
|    // don't run ChromeBrowserMainParts code where it's done for Chrome.
 | 
| -  if (!global_)
 | 
| +  // Some tests depend on the enable and disable features flag switch, though,
 | 
| +  // so we can still add those even though AllStatesToString() will be a no-op.
 | 
| +  if (!global_) {
 | 
| +    AddFeatureAndFieldTrialFlags(enable_features_switch,
 | 
| +                                 disable_features_switch, cmd_line);
 | 
|      return;
 | 
| +  }
 | 
|  
 | 
|  #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE)
 | 
|    // Use shared memory to pass the state if the feature is enabled, otherwise
 | 
| @@ -869,7 +909,8 @@ void FieldTrialList::CopyFieldTrialStateToFlags(
 | 
|      // If the readonly handle didn't get duplicated properly, then fallback to
 | 
|      // original behavior.
 | 
|      if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) {
 | 
| -      AddForceFieldTrialsFlag(cmd_line);
 | 
| +      AddFeatureAndFieldTrialFlags(enable_features_switch,
 | 
| +                                   disable_features_switch, cmd_line);
 | 
|        return;
 | 
|      }
 | 
|  
 | 
| @@ -895,7 +936,8 @@ void FieldTrialList::CopyFieldTrialStateToFlags(
 | 
|    }
 | 
|  #endif
 | 
|  
 | 
| -  AddForceFieldTrialsFlag(cmd_line);
 | 
| +  AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch,
 | 
| +                               cmd_line);
 | 
|  }
 | 
|  
 | 
|  // static
 | 
| @@ -1171,6 +1213,10 @@ void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() {
 | 
|      AddToAllocatorWhileLocked(registered.second);
 | 
|    }
 | 
|  
 | 
| +  // Add all existing features.
 | 
| +  FeatureList::GetInstance()->AddFeaturesToAllocator(
 | 
| +      global_->field_trial_allocator_.get());
 | 
| +
 | 
|  #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE)
 | 
|    // Set |readonly_allocator_handle_| so we can pass it to be inherited and
 | 
|    // via the command line.
 | 
| 
 |