// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/variations/variations_seed_processor.h"

#include <stddef.h>

#include <map>
#include <vector>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "components/variations/client_filterable_state.h"
#include "components/variations/processed_study.h"
#include "components/variations/study_filtering.h"
#include "components/variations/variations_associated_data.h"

namespace variations {

namespace {

// Associates the variations params of |experiment|, if present.
void RegisterExperimentParams(const Study& study,
                              const Study_Experiment& experiment) {
  std::map<std::string, std::string> params;
  for (int i = 0; i < experiment.param_size(); ++i) {
    if (experiment.param(i).has_name() && experiment.param(i).has_value())
      params[experiment.param(i).name()] = experiment.param(i).value();
  }
  if (!params.empty())
    AssociateVariationParams(study.name(), experiment.name(), params);
}

// If there are variation ids associated with |experiment|, register the
// variation ids.
void RegisterVariationIds(const Study_Experiment& experiment,
                          const std::string& trial_name) {
  if (experiment.has_google_web_experiment_id()) {
    const VariationID variation_id =
        static_cast<VariationID>(experiment.google_web_experiment_id());
    AssociateGoogleVariationIDForce(GOOGLE_WEB_PROPERTIES,
                                    trial_name,
                                    experiment.name(),
                                    variation_id);
  }
  if (experiment.has_google_web_trigger_experiment_id()) {
    const VariationID variation_id =
        static_cast<VariationID>(experiment.google_web_trigger_experiment_id());
    AssociateGoogleVariationIDForce(GOOGLE_WEB_PROPERTIES_TRIGGER,
                                    trial_name,
                                    experiment.name(),
                                    variation_id);
  }
  if (experiment.has_chrome_sync_experiment_id()) {
    const VariationID variation_id =
        static_cast<VariationID>(experiment.chrome_sync_experiment_id());
    AssociateGoogleVariationIDForce(CHROME_SYNC_EVENT_LOGGER, trial_name,
                                    experiment.name(), variation_id);
  }
}

// Executes |callback| on every override defined by |experiment|.
void ApplyUIStringOverrides(
    const Study_Experiment& experiment,
    const VariationsSeedProcessor::UIStringOverrideCallback& callback) {
  UMA_HISTOGRAM_COUNTS_100("Variations.StringsOverridden",
                           experiment.override_ui_string_size());
  for (int i = 0; i < experiment.override_ui_string_size(); ++i) {
    const Study_Experiment_OverrideUIString& override =
        experiment.override_ui_string(i);
    callback.Run(override.name_hash(), base::UTF8ToUTF16(override.value()));
  }
}

// Forces the specified |experiment| to be enabled in |study|.
void ForceExperimentState(
    const Study& study,
    const Study_Experiment& experiment,
    const VariationsSeedProcessor::UIStringOverrideCallback& override_callback,
    base::FieldTrial* trial) {
  RegisterExperimentParams(study, experiment);
  RegisterVariationIds(experiment, study.name());
  if (study.activation_type() == Study_ActivationType_ACTIVATION_AUTO) {
    // This call must happen after all params have been registered for the
    // trial. Otherwise, since we look up params by trial and group name, the
    // params won't be registered under the correct key.
    trial->group();
    // UI Strings can only be overridden from ACTIVATION_AUTO experiments.
    ApplyUIStringOverrides(experiment, override_callback);
  }
}

// Registers feature overrides for the chosen experiment in the specified study.
void RegisterFeatureOverrides(const ProcessedStudy& processed_study,
                              base::FieldTrial* trial,
                              base::FeatureList* feature_list) {
  const std::string& group_name = trial->GetGroupNameWithoutActivation();
  int experiment_index = processed_study.GetExperimentIndexByName(group_name);
  // If the chosen experiment was not found in the study, simply return.
  // Although not normally expected, but could happen in exception cases, see
  // tests: ExpiredStudy_NoDefaultGroup, ExistingFieldTrial_ExpiredByConfig
  if (experiment_index == -1)
    return;

  const Study& study = *processed_study.study();
  const Study_Experiment& experiment = study.experiment(experiment_index);

  // Process all the features to enable.
  int feature_count = experiment.feature_association().enable_feature_size();
  for (int i = 0; i < feature_count; ++i) {
    feature_list->RegisterFieldTrialOverride(
        experiment.feature_association().enable_feature(i),
        base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
  }

  // Process all the features to disable.
  feature_count = experiment.feature_association().disable_feature_size();
  for (int i = 0; i < feature_count; ++i) {
    feature_list->RegisterFieldTrialOverride(
        experiment.feature_association().disable_feature(i),
        base::FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
  }

  // Associate features for groups that do not specify them manually (e.g.
  // "Default" group), so that such groups are reported.
  if (!experiment.has_feature_association()) {
    for (const auto& feature_name : processed_study.associated_features()) {
      feature_list->RegisterFieldTrialOverride(
          feature_name, base::FeatureList::OVERRIDE_USE_DEFAULT, trial);
    }
  }
}

// Checks if |experiment| is associated with a forcing flag or feature and if it
// is, returns whether it should be forced enabled based on the |command_line|
// or |feature_list| state.
bool ShouldForceExperiment(const Study_Experiment& experiment,
                           const base::CommandLine& command_line,
                           const base::FeatureList& feature_list) {
  if (experiment.feature_association().has_forcing_feature_on()) {
    return feature_list.IsFeatureOverriddenFromCommandLine(
        experiment.feature_association().forcing_feature_on(),
        base::FeatureList::OVERRIDE_ENABLE_FEATURE);
  }
  if (experiment.feature_association().has_forcing_feature_off()) {
    return feature_list.IsFeatureOverriddenFromCommandLine(
        experiment.feature_association().forcing_feature_off(),
        base::FeatureList::OVERRIDE_DISABLE_FEATURE);
  }
  if (experiment.has_forcing_flag())
    return command_line.HasSwitch(experiment.forcing_flag());
  return false;
}

}  // namespace

VariationsSeedProcessor::VariationsSeedProcessor() {
}

VariationsSeedProcessor::~VariationsSeedProcessor() {
}

void VariationsSeedProcessor::CreateTrialsFromSeed(
    const VariationsSeed& seed,
    const ClientFilterableState& client_state,
    const UIStringOverrideCallback& override_callback,
    const base::FieldTrial::EntropyProvider* low_entropy_provider,
    base::FeatureList* feature_list) {
  std::vector<ProcessedStudy> filtered_studies;
  FilterAndValidateStudies(seed, client_state, &filtered_studies);

  for (const ProcessedStudy& study : filtered_studies) {
    CreateTrialFromStudy(study, override_callback, low_entropy_provider,
                         feature_list);
  }
}

// static
bool VariationsSeedProcessor::ShouldStudyUseLowEntropy(const Study& study) {
  for (int i = 0; i < study.experiment_size(); ++i) {
    const Study_Experiment& experiment = study.experiment(i);
    if (experiment.has_google_web_experiment_id() ||
        experiment.has_google_web_trigger_experiment_id() ||
        experiment.has_chrome_sync_experiment_id()) {
      return true;
    }
  }
  return false;
}

void VariationsSeedProcessor::CreateTrialFromStudy(
    const ProcessedStudy& processed_study,
    const UIStringOverrideCallback& override_callback,
    const base::FieldTrial::EntropyProvider* low_entropy_provider,
    base::FeatureList* feature_list) {
  const Study& study = *processed_study.study();

  // If the trial already exists, check if the selected group exists in the
  // |processed_study|. If not, there is nothing to do here.
  base::FieldTrial* existing_trial = base::FieldTrialList::Find(study.name());
  if (existing_trial) {
    int experiment_index = processed_study.GetExperimentIndexByName(
        existing_trial->GetGroupNameWithoutActivation());
    if (experiment_index == -1)
      return;
  }

  // Check if any experiments need to be forced due to a command line
  // flag. Force the first experiment with an existing flag.
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  for (int i = 0; i < study.experiment_size(); ++i) {
    const Study_Experiment& experiment = study.experiment(i);
    if (ShouldForceExperiment(experiment, *command_line, *feature_list)) {
      base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
          study.name(), experiment.name());
      // If |trial| is null, then there might already be a trial forced to a
      // different group (e.g. via --force-fieldtrials). Break out of the loop,
      // but don't return, so that variation ids and params for the selected
      // group will still be picked up.
      if (!trial)
        break;

      if (experiment.feature_association().has_forcing_feature_on()) {
        feature_list->AssociateReportingFieldTrial(
            experiment.feature_association().forcing_feature_on(),
            base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
      } else if (experiment.feature_association().has_forcing_feature_off()) {
        feature_list->AssociateReportingFieldTrial(
            experiment.feature_association().forcing_feature_off(),
            base::FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
      }
      ForceExperimentState(study, experiment, override_callback, trial);
      return;
    }
  }

  uint32_t randomization_seed = 0;
  base::FieldTrial::RandomizationType randomization_type =
      base::FieldTrial::SESSION_RANDOMIZED;
  if (study.has_consistency() &&
      study.consistency() == Study_Consistency_PERMANENT &&
      // If all assignments are to a single group, no need to enable one time
      // randomization (which is more expensive to compute), since the result
      // will be the same.
      !processed_study.all_assignments_to_one_group()) {
    randomization_type = base::FieldTrial::ONE_TIME_RANDOMIZED;
    if (study.has_randomization_seed())
      randomization_seed = study.randomization_seed();
  }

  // The trial is created without specifying an expiration date because the
  // expiration check in field_trial.cc is based on the build date. Instead,
  // the expiration check using |reference_date| is done explicitly below.
  scoped_refptr<base::FieldTrial> trial(
      base::FieldTrialList::FactoryGetFieldTrialWithRandomizationSeed(
          study.name(), processed_study.total_probability(),
          processed_study.GetDefaultExperimentName(),
          base::FieldTrialList::kNoExpirationYear, 1, 1, randomization_type,
          randomization_seed, nullptr,
          ShouldStudyUseLowEntropy(study) ? low_entropy_provider : nullptr));

  bool has_overrides = false;
  bool enables_or_disables_features = false;
  for (int i = 0; i < study.experiment_size(); ++i) {
    const Study_Experiment& experiment = study.experiment(i);
    RegisterExperimentParams(study, experiment);

    // Groups with forcing flags have probability 0 and will never be selected.
    // Therefore, there's no need to add them to the field trial.
    if (experiment.has_forcing_flag() ||
        experiment.feature_association().has_forcing_feature_on() ||
        experiment.feature_association().has_forcing_feature_off()) {
      continue;
    }

    if (experiment.name() != study.default_experiment_name())
      trial->AppendGroup(experiment.name(), experiment.probability_weight());

    RegisterVariationIds(experiment, study.name());

    has_overrides = has_overrides || experiment.override_ui_string_size() > 0;
    if (experiment.feature_association().enable_feature_size() != 0 ||
        experiment.feature_association().disable_feature_size() != 0) {
      enables_or_disables_features = true;
    }
  }

  trial->SetForced();
  if (processed_study.is_expired())
    trial->Disable();

  if (enables_or_disables_features)
    RegisterFeatureOverrides(processed_study, trial.get(), feature_list);

  if (study.activation_type() == Study_ActivationType_ACTIVATION_AUTO) {
    // This call must happen after all params have been registered for the
    // trial. Otherwise, since we look up params by trial and group name, the
    // params won't be registered under the correct key.
    const std::string& group_name = trial->group_name();

    // Don't try to apply overrides if none of the experiments in this study had
    // any.
    if (!has_overrides)
      return;

    // UI Strings can only be overridden from ACTIVATION_AUTO experiments.
    int experiment_index = processed_study.GetExperimentIndexByName(group_name);
    // If the chosen experiment was not found in the study, simply return.
    // Although not normally expected, but could happen in exception cases, see
    // tests: ExpiredStudy_NoDefaultGroup, ExistingFieldTrial_ExpiredByConfig
    if (experiment_index != -1) {
      ApplyUIStringOverrides(study.experiment(experiment_index),
                             override_callback);
    }
  }
}

}  // namespace variations
