Registering field trial for a feature overridden in chrome://flags.

Variation parameters can be overridden via chrome://flags. Internally, a
fresh trial group is created with the specified parameters. Previously,
the trial was not registered for the associated feature.

This CL registers the trial for the given feature.

BUG=625993

Review-Url: https://codereview.chromium.org/2129543002
Cr-Commit-Position: refs/heads/master@{#405496}
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc
index 441949bc..4e2b736 100644
--- a/components/flags_ui/flags_state.cc
+++ b/components/flags_ui/flags_state.cc
@@ -197,7 +197,7 @@
 // been created (e.g. via command-line switches that take precedence over
 // about:flags). In the trial, the function creates a new constant group called
 // |kTrialGroupAboutFlags|.
-void RegisterFeatureVariationParameters(
+base::FieldTrial* RegisterFeatureVariationParameters(
     const std::string& feature_trial_name,
     const FeatureEntry::FeatureVariation* feature_variation) {
   std::map<std::string, std::string> params;
@@ -211,18 +211,19 @@
 
   bool success = variations::AssociateVariationParams(
       feature_trial_name, internal::kTrialGroupAboutFlags, params);
-  if (success) {
-    // Successful association also means that no group is created and selected
-    // for the trial, yet. Thus, create the trial to select the group. This way,
-    // the parameters cannot get overwritten in later phases (such as from the
-    // server).
-    base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
-        feature_trial_name, internal::kTrialGroupAboutFlags);
-    if (!trial) {
-      DLOG(WARNING) << "Could not create the trial " << feature_trial_name
-                    << " with group " << internal::kTrialGroupAboutFlags;
-    }
+  if (!success)
+    return nullptr;
+  // Successful association also means that no group is created and selected
+  // for the trial, yet. Thus, create the trial to select the group. This way,
+  // the parameters cannot get overwritten in later phases (such as from the
+  // server).
+  base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
+      feature_trial_name, internal::kTrialGroupAboutFlags);
+  if (!trial) {
+    DLOG(WARNING) << "Could not create the trial " << feature_trial_name
+                  << " with group " << internal::kTrialGroupAboutFlags;
   }
+  return trial;
 }
 
 }  // namespace
@@ -436,7 +437,8 @@
 }
 
 void FlagsState::RegisterAllFeatureVariationParameters(
-    FlagsStorage* flags_storage) {
+    FlagsStorage* flags_storage,
+    base::FeatureList* feature_list) {
   std::set<std::string> enabled_entries;
   GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries);
 
@@ -448,20 +450,16 @@
             e.VariationForOption(j);
         if (e.StateForOption(j) == FeatureEntry::FeatureState::ENABLED &&
             enabled_entries.count(e.NameForOption(j))) {
-          // If the option is enabled by the user, register it.
-          RegisterFeatureVariationParameters(e.feature_trial_name, variation);
-          // TODO(jkrcal) The code does not associate the feature with the field
-          // trial |e.feature_trial_name|. The reason is that features
-          // overridden in chrome://flags are translated to command-line flags
-          // and thus treated earlier in the initialization. The fix requires
-          // larger changes. As a result:
-          //  - the API calls to variations::GetVariationParamValueByFeature and
-          //    to variations::GetVariationParamsByFeature do not work; and
-          //  - the API call to base::FeatureList::IsEnabled does not mark the
-          //    field trial as active (and the trial does not appear in UMA).
-          // If the code calls variations::GetVariationParamValue or
-          // variations::GetVariationParams providing the trial name, everything
-          // should work fine.
+          // If the option is selected by the user & has variation, register it.
+          base::FieldTrial* field_trial = RegisterFeatureVariationParameters(
+              e.feature_trial_name, variation);
+
+          if (!field_trial)
+            continue;
+          feature_list->RegisterFieldTrialOverride(
+              e.feature->name,
+              base::FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE,
+              field_trial);
         }
       }
     }
diff --git a/components/flags_ui/flags_state.h b/components/flags_ui/flags_state.h
index 6f0ff1f..2be899c 100644
--- a/components/flags_ui/flags_state.h
+++ b/components/flags_ui/flags_state.h
@@ -16,6 +16,7 @@
 #include "base/macros.h"
 
 namespace base {
+class FeatureList;
 class ListValue;
 }
 
@@ -80,9 +81,12 @@
   void ResetAllFlags(FlagsStorage* flags_storage);
   void Reset();
 
-  // Registers variations parameter values stored in |flags_storage| (previously
-  // selected in about:flags).
-  void RegisterAllFeatureVariationParameters(FlagsStorage* flags_storage);
+  // Registers variations parameter values selected for features in about:flags.
+  // The selected flags are retrieved from |flags_storage|, the registered
+  // variation parameters are connected to their corresponding features in
+  // |feature_list|.
+  void RegisterAllFeatureVariationParameters(FlagsStorage* flags_storage,
+                                             base::FeatureList* feature_list);
 
   // Gets the list of feature entries. Entries that are available for the
   // current platform are appended to |supported_entries|; all other entries are
diff --git a/components/flags_ui/flags_state_unittest.cc b/components/flags_ui/flags_state_unittest.cc
index cc0a206..f8a908fd 100644
--- a/components/flags_ui/flags_state_unittest.cc
+++ b/components/flags_ui/flags_state_unittest.cc
@@ -267,10 +267,13 @@
 
 TEST_F(FlagsStateTest, RegisterAllFeatureVariationParameters) {
   const FeatureEntry& entry = kEntries[7];
+  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+
   // Select the "Default" variation.
   flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
                                        true);
-  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_);
+  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
+                                                      feature_list.get());
   // No value should be associated.
   EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam));
   // The trial should not be created.
@@ -281,7 +284,8 @@
   flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1),
                                        true);
 
-  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_);
+  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
+                                                      feature_list.get());
   // No value should be associated as this is the default option.
   EXPECT_EQ("",
             variations::GetVariationParamValue(kTestTrial, kTestParam));
@@ -295,7 +299,8 @@
   // Select the only one variation.
   flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
                                        true);
-  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_);
+  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
+                                                      feature_list.get());
   // Associating for the second time should not change the value.
   EXPECT_EQ("",
             variations::GetVariationParamValue(kTestTrial, kTestParam));
@@ -303,13 +308,26 @@
 
 TEST_F(FlagsStateTest, RegisterAllFeatureVariationParametersNonDefault) {
   const FeatureEntry& entry = kEntries[7];
+  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+
   // Select the only one variation.
   flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
                                        true);
-  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_);
+  flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
+                                                      feature_list.get());
+
+  // Set the feature_list as the main instance so that
+  // variations::GetVariationParamValueByFeature below works.
+  base::FeatureList::ClearInstanceForTesting();
+  base::FeatureList::SetInstance(std::move(feature_list));
+
   // The param should have the value predefined in this variation.
   EXPECT_EQ(kTestParamValue,
             variations::GetVariationParamValue(kTestTrial, kTestParam));
+
+  // The value should be associated also via the name of the feature.
+  EXPECT_EQ(kTestParamValue, variations::GetVariationParamValueByFeature(
+                                  kTestFeature2, kTestParam));
 }
 
 base::CommandLine::StringType CreateSwitch(const std::string& value) {