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. |