// 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 "chrome/browser/profile_resetter/automatic_profile_resetter.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h"
#include "chrome/browser/profile_resetter/jtl_interpreter.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "components/variations/variations_associated_data.h"
#include "content/public/browser/browser_thread.h"
#include "grit/browser_resources.h"
#include "ui/base/resource/resource_bundle.h"


// Helpers -------------------------------------------------------------------

namespace {

// Name constants for the field trial behind which we enable this feature.
const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset";
const char kAutomaticProfileResetStudyDryRunGroupName[] = "DryRun";
const char kAutomaticProfileResetStudyEnabledGroupName[] = "Enabled";
#if defined(GOOGLE_CHROME_BUILD)
const char kAutomaticProfileResetStudyProgramParameterName[] = "program";
const char kAutomaticProfileResetStudyHashSeedParameterName[] = "hash_seed";
#endif

// How long to wait after start-up before unleashing the evaluation flow.
const int64 kEvaluationFlowDelayInSeconds = 55;

// Keys used in the input dictionary of the program.
const char kDefaultSearchProviderKey[] = "default_search_provider";
const char kDefaultSearchProviderIsUserControlledKey[] =
    "default_search_provider_iuc";
const char kLoadedModuleDigestsKey[] = "loaded_modules";
const char kLocalStateKey[] = "local_state";
const char kLocalStateIsUserControlledKey[] = "local_state_iuc";
const char kSearchProvidersKey[] = "search_providers";
const char kUserPreferencesKey[] = "preferences";
const char kUserPreferencesIsUserControlledKey[] = "preferences_iuc";

// Keys used in the output dictionary of the program.
const char kCombinedStatusMaskKeys[][26] = {
    "combined_status_mask_bit1", "combined_status_mask_bit2",
    "combined_status_mask_bit3", "combined_status_mask_bit4"};
const char kHadPromptedAlreadyKey[] = "had_prompted_already";
const char kSatisfiedCriteriaMaskKeys[][29] = {"satisfied_criteria_mask_bit1",
                                               "satisfied_criteria_mask_bit2"};

// Keys used in both the input and output dictionary of the program.
const char kMementoValueInFileKey[] = "memento_value_in_file";
const char kMementoValueInLocalStateKey[] = "memento_value_in_local_state";
const char kMementoValueInPrefsKey[] = "memento_value_in_prefs";

// Number of bits, and maximum value (exclusive) for the mask whose bits
// indicate which of reset criteria were satisfied.
const size_t kSatisfiedCriteriaMaskNumberOfBits = 2u;
const uint32 kSatisfiedCriteriaMaskMaximumValue =
    (1u << kSatisfiedCriteriaMaskNumberOfBits);

// Number of bits, and maximum value (exclusive) for the mask whose bits
// indicate if any of reset criteria were satisfied, and which of the mementos
// were already present.
const size_t kCombinedStatusMaskNumberOfBits = 4u;
const uint32 kCombinedStatusMaskMaximumValue =
    (1u << kCombinedStatusMaskNumberOfBits);

COMPILE_ASSERT(
    arraysize(kSatisfiedCriteriaMaskKeys) == kSatisfiedCriteriaMaskNumberOfBits,
    satisfied_criteria_mask_bits_mismatch);
COMPILE_ASSERT(
    arraysize(kCombinedStatusMaskKeys) == kCombinedStatusMaskNumberOfBits,
    combined_status_mask_bits_mismatch);

// Returns whether or not a dry-run shall be performed.
bool ShouldPerformDryRun() {
  return StartsWithASCII(
      base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName),
      kAutomaticProfileResetStudyDryRunGroupName, true);
}

// Returns whether or not a live-run shall be performed.
bool ShouldPerformLiveRun() {
  return StartsWithASCII(
      base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName),
      kAutomaticProfileResetStudyEnabledGroupName, true);
}

// If the currently active experiment group prescribes a |program| and
// |hash_seed| to use instead of the baked-in ones, retrieves those and returns
// true. Otherwise, returns false.
bool GetProgramAndHashSeedOverridesFromExperiment(std::string* program,
                                                  std::string* hash_seed) {
  DCHECK(program);
  DCHECK(hash_seed);
#if defined(GOOGLE_CHROME_BUILD)
  std::map<std::string, std::string> params;
  chrome_variations::GetVariationParams(kAutomaticProfileResetStudyName,
                                        &params);
  if (params.count(kAutomaticProfileResetStudyProgramParameterName) &&
      params.count(kAutomaticProfileResetStudyHashSeedParameterName)) {
    program->swap(params[kAutomaticProfileResetStudyProgramParameterName]);
    hash_seed->swap(params[kAutomaticProfileResetStudyHashSeedParameterName]);
    return true;
  }
#endif
  return false;
}

// Takes |pref_name_to_value_map|, which shall be a deep-copy of all preferences
// in |source| without path expansion; and (1.) creates a sub-tree from it named
// |value_tree_key| in |target_dictionary| with path expansion, and (2.) also
// creates an isomorphic sub-tree under the key |is_user_controlled_tree_key|
// that contains only Boolean values indicating whether or not the corresponding
// preference is coming from the 'user' PrefStore.
void BuildSubTreesFromPreferences(
    scoped_ptr<base::DictionaryValue> pref_name_to_value_map,
    const PrefService* source,
    const char* value_tree_key,
    const char* is_user_controlled_tree_key,
    base::DictionaryValue* target_dictionary) {
  std::vector<std::string> pref_names;
  pref_names.reserve(pref_name_to_value_map->size());
  for (base::DictionaryValue::Iterator it(*pref_name_to_value_map);
       !it.IsAtEnd(); it.Advance())
    pref_names.push_back(it.key());

  base::DictionaryValue* value_tree = new base::DictionaryValue;
  base::DictionaryValue* is_user_controlled_tree = new base::DictionaryValue;
  for (std::vector<std::string>::const_iterator it = pref_names.begin();
       it != pref_names.end(); ++it) {
    scoped_ptr<Value> pref_value_owned;
    if (pref_name_to_value_map->RemoveWithoutPathExpansion(*it,
                                                           &pref_value_owned)) {
      value_tree->Set(*it, pref_value_owned.release());
      const PrefService::Preference* pref = source->FindPreference(it->c_str());
      is_user_controlled_tree->Set(
          *it, new base::FundamentalValue(pref->IsUserControlled()));
    }
  }
  target_dictionary->Set(value_tree_key, value_tree);
  target_dictionary->Set(is_user_controlled_tree_key, is_user_controlled_tree);
}

}  // namespace


// AutomaticProfileResetter::InputBuilder ------------------------------------

// Collects all the information that is required by the evaluator program to
// assess whether or not the conditions for showing the reset prompt are met.
//
// This necessitates a lot of work that has to be performed on the UI thread,
// such as: accessing the Preferences, Local State, and TemplateURLService.
// In order to keep the browser responsive, the UI thread shall not be blocked
// for long consecutive periods of time. Unfortunately, we cannot reduce the
// total amount of work. Instead, what this class does is to split the work into
// shorter tasks that are posted one-at-a-time to the UI thread in a serial
// fashion, so as to give a chance to run other tasks that have accumulated in
// the meantime.
class AutomaticProfileResetter::InputBuilder
    : public base::SupportsWeakPtr<InputBuilder> {
 public:
  typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)>
      ProgramInputCallback;

  // The dependencies must have been initialized through |delegate|, i.e. the
  // RequestCallback[...] methods must have already fired before calling this.
  InputBuilder(Profile* profile, AutomaticProfileResetterDelegate* delegate)
      : profile_(profile),
        delegate_(delegate),
        memento_in_prefs_(profile_),
        memento_in_local_state_(profile_),
        memento_in_file_(profile_) {}
  ~InputBuilder() {}

  // Assembles the data required by the evaluator program into a dictionary
  // format, and posts it back to the UI thread with |callback| once ready. In
  // order not to block the UI thread for long consecutive periods of time, the
  // work is divided into smaller tasks, see class comment above for details.
  // It is safe to destroy |this| immediately from within the |callback|.
  void BuildEvaluatorProgramInput(const ProgramInputCallback& callback) {
    DCHECK(!data_);
    DCHECK(!callback.is_null());
    data_.reset(new base::DictionaryValue);
    callback_ = callback;

    AddAsyncTask(base::Bind(&InputBuilder::IncludeMementoValues, AsWeakPtr()));
    AddTask(base::Bind(&InputBuilder::IncludeUserPreferences, AsWeakPtr()));
    AddTask(base::Bind(&InputBuilder::IncludeLocalState, AsWeakPtr()));
    AddTask(base::Bind(&InputBuilder::IncludeSearchEngines, AsWeakPtr()));
    AddTask(base::Bind(&InputBuilder::IncludeLoadedModules, AsWeakPtr()));

    // Each task will post the next one. Just trigger the chain reaction.
    PostNextTask();
  }

 private:
  // Asynchronous task that includes memento values (or empty strings in case
  // mementos are not there).
  void IncludeMementoValues() {
    data_->SetString(kMementoValueInPrefsKey, memento_in_prefs_.ReadValue());
    data_->SetString(kMementoValueInLocalStateKey,
                     memento_in_local_state_.ReadValue());
    memento_in_file_.ReadValue(base::Bind(
        &InputBuilder::IncludeFileBasedMementoCallback, AsWeakPtr()));
  }

  // Called back by |memento_in_file_| once the |memento_value| has been read.
  void IncludeFileBasedMementoCallback(const std::string& memento_value) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    data_->SetString(kMementoValueInFileKey, memento_value);
    // As an asynchronous task, we need to take care of posting the next task.
    PostNextTask();
  }

  // Task that includes all user (i.e. profile-specific) preferences, along with
  // information about whether the value is coming from the 'user' PrefStore.
  // This is the most expensive operation, so it is itself split into two parts.
  void IncludeUserPreferences() {
    PrefService* prefs = profile_->GetPrefs();
    DCHECK(prefs);
    scoped_ptr<base::DictionaryValue> pref_name_to_value_map(
        prefs->GetPreferenceValuesWithoutPathExpansion());
    AddTask(base::Bind(&InputBuilder::IncludeUserPreferencesPartTwo,
                       AsWeakPtr(),
                       base::Passed(&pref_name_to_value_map)));
  }

  // Second part to above.
  void IncludeUserPreferencesPartTwo(
      scoped_ptr<base::DictionaryValue> pref_name_to_value_map) {
    PrefService* prefs = profile_->GetPrefs();
    DCHECK(prefs);
    BuildSubTreesFromPreferences(
        pref_name_to_value_map.Pass(),
        prefs,
        kUserPreferencesKey,
        kUserPreferencesIsUserControlledKey,
        data_.get());
  }

  // Task that includes all local state (i.e. shared) preferences, along with
  // information about whether the value is coming from the 'user' PrefStore.
  void IncludeLocalState() {
    PrefService* local_state = g_browser_process->local_state();
    DCHECK(local_state);
    scoped_ptr<base::DictionaryValue> pref_name_to_value_map(
        local_state->GetPreferenceValuesWithoutPathExpansion());
    BuildSubTreesFromPreferences(
        pref_name_to_value_map.Pass(),
        local_state,
        kLocalStateKey,
        kLocalStateIsUserControlledKey,
        data_.get());
  }

  // Task that includes all information related to search engines.
  void IncludeSearchEngines() {
    scoped_ptr<base::DictionaryValue> default_search_provider_details(
        delegate_->GetDefaultSearchProviderDetails());
    data_->Set(kDefaultSearchProviderKey,
               default_search_provider_details.release());

    scoped_ptr<base::ListValue> search_providers_details(
        delegate_->GetPrepopulatedSearchProvidersDetails());
    data_->Set(kSearchProvidersKey, search_providers_details.release());

    data_->SetBoolean(kDefaultSearchProviderIsUserControlledKey,
                      !delegate_->IsDefaultSearchProviderManaged());
  }

  // Task that includes information about loaded modules.
  void IncludeLoadedModules() {
    scoped_ptr<base::ListValue> loaded_module_digests(
        delegate_->GetLoadedModuleNameDigests());
    data_->Set(kLoadedModuleDigestsKey, loaded_module_digests.release());
  }

  // -------------------------------------------------------------------------

  // Adds a |task| that can do as much asynchronous processing as it wants, but
  // will need to finally call PostNextTask() on the UI thread when done.
  void AddAsyncTask(const base::Closure& task) {
    task_queue_.push(task);
  }

  // Convenience wrapper for synchronous tasks.
  void SynchronousTaskWrapper(const base::Closure& task) {
    base::ElapsedTimer timer;
    task.Run();
    UMA_HISTOGRAM_CUSTOM_TIMES(
        "AutomaticProfileReset.InputBuilder.TaskDuration",
        timer.Elapsed(),
        base::TimeDelta::FromMilliseconds(1),
        base::TimeDelta::FromSeconds(2),
        50);
    PostNextTask();
  }

  // Adds a task that needs to finish synchronously. In exchange, PostNextTask()
  // is called automatically when the |task| returns, and execution time is
  // measured.
  void AddTask(const base::Closure& task) {
    task_queue_.push(
        base::Bind(&InputBuilder::SynchronousTaskWrapper, AsWeakPtr(), task));
  }

  // Posts the next task from the |task_queue_|, unless it is exhausted, in
  // which case it posts |callback_| to return with the results.
  void PostNextTask() {
    base::Closure next_task;
    if (task_queue_.empty()) {
      next_task = base::Bind(callback_, base::Passed(&data_));
    } else {
      next_task = task_queue_.front();
      task_queue_.pop();
    }
    content::BrowserThread::PostTask(
        content::BrowserThread::UI, FROM_HERE, next_task);
  }

  Profile* profile_;
  AutomaticProfileResetterDelegate* delegate_;
  ProgramInputCallback callback_;

  PreferenceHostedPromptMemento memento_in_prefs_;
  LocalStateHostedPromptMemento memento_in_local_state_;
  FileHostedPromptMemento memento_in_file_;

  scoped_ptr<base::DictionaryValue> data_;
  std::queue<base::Closure> task_queue_;

  DISALLOW_COPY_AND_ASSIGN(InputBuilder);
};


// AutomaticProfileResetter::EvaluationResults -------------------------------

// Encapsulates the output values extracted from the evaluator program.
struct AutomaticProfileResetter::EvaluationResults {
  EvaluationResults()
      : had_prompted_already(false),
        satisfied_criteria_mask(0),
        combined_status_mask(0) {}

  std::string memento_value_in_prefs;
  std::string memento_value_in_local_state;
  std::string memento_value_in_file;

  bool had_prompted_already;
  uint32 satisfied_criteria_mask;
  uint32 combined_status_mask;
};


// AutomaticProfileResetter --------------------------------------------------

AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile)
    : profile_(profile),
      state_(STATE_UNINITIALIZED),
      enumeration_of_loaded_modules_ready_(false),
      template_url_service_ready_(false),
      has_already_dismissed_prompt_(false),
      weak_ptr_factory_(this) {
  DCHECK(profile_);
}

AutomaticProfileResetter::~AutomaticProfileResetter() {}

void AutomaticProfileResetter::Initialize() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_UNINITIALIZED);

  if (!ShouldPerformDryRun() && !ShouldPerformLiveRun()) {
    state_ = STATE_DISABLED;
    return;
  }

  if (!GetProgramAndHashSeedOverridesFromExperiment(&program_, &hash_seed_)) {
    ui::ResourceBundle& resources(ui::ResourceBundle::GetSharedInstance());
    if (ShouldPerformLiveRun()) {
      program_ = resources.GetRawDataResource(
          IDR_AUTOMATIC_PROFILE_RESET_RULES).as_string();
      hash_seed_ = resources.GetRawDataResource(
          IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED).as_string();
    } else {  // ShouldPerformDryRun()
      program_ = resources.GetRawDataResource(
          IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY).as_string();
      hash_seed_ = resources.GetRawDataResource(
          IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY).as_string();
    }
  }

  delegate_.reset(new AutomaticProfileResetterDelegateImpl(
      profile_, ProfileResetter::ALL));
  task_runner_for_waiting_ =
      content::BrowserThread::GetMessageLoopProxyForThread(
          content::BrowserThread::UI);

  state_ = STATE_INITIALIZED;
}

void AutomaticProfileResetter::Activate() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED);

  if (state_ == STATE_INITIALIZED) {
    if (!program_.empty()) {
      // Some steps in the flow (e.g. loaded modules, file-based memento) are
      // IO-intensive, so defer execution until some time later.
      task_runner_for_waiting_->PostDelayedTask(
          FROM_HERE,
          base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow,
                     weak_ptr_factory_.GetWeakPtr()),
          base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds));
    } else {
      // Terminate early if there is no program included (nor set by tests).
      state_ = STATE_DISABLED;
    }
  }
}

void AutomaticProfileResetter::TriggerProfileReset(bool send_feedback) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE);

  state_ = STATE_PERFORMING_RESET;

  ReportPromptResult(PROMPT_ACTION_RESET);
  delegate_->TriggerProfileSettingsReset(
      send_feedback,
      base::Bind(&AutomaticProfileResetter::OnProfileSettingsResetCompleted,
                 weak_ptr_factory_.GetWeakPtr()));
}

void AutomaticProfileResetter::SkipProfileReset() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE);

  ReportPromptResult(PROMPT_ACTION_NO_RESET);
  delegate_->DismissPrompt();
  FinishResetPromptFlow();
}

bool AutomaticProfileResetter::IsResetPromptFlowActive() const {
  return state_ == STATE_HAS_TRIGGERED_PROMPT ||
      state_ == STATE_HAS_SHOWN_BUBBLE;
}

void AutomaticProfileResetter::NotifyDidShowResetBubble() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_HAS_TRIGGERED_PROMPT);

  state_ = STATE_HAS_SHOWN_BUBBLE;

  PersistMementos();
  ReportPromptResult(PROMPT_SHOWN_BUBBLE);
}

void AutomaticProfileResetter::NotifyDidOpenWebUIResetDialog() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  // This notification is invoked unconditionally by the WebUI, only care about
  // it when the prompt flow is currently active (and not yet resetting).
  if (state_ == STATE_HAS_TRIGGERED_PROMPT ||
      state_ == STATE_HAS_SHOWN_BUBBLE) {
    has_already_dismissed_prompt_ = true;
    delegate_->DismissPrompt();
  }
}

void AutomaticProfileResetter::NotifyDidCloseWebUIResetDialog(
    bool performed_reset) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  // This notification is invoked unconditionally by the WebUI, only care about
  // it when the prompt flow is currently active (and not yet resetting).
  if (state_ == STATE_HAS_TRIGGERED_PROMPT ||
      state_ == STATE_HAS_SHOWN_BUBBLE) {
    if (!has_already_dismissed_prompt_)
      delegate_->DismissPrompt();
    if (state_ == STATE_HAS_TRIGGERED_PROMPT) {
      PersistMementos();
      ReportPromptResult(performed_reset ?
          PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_RESET :
          PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_NO_RESET);
    } else {  // if (state_ == STATE_HAS_SHOWN_PROMPT)
      ReportPromptResult(performed_reset ?
          PROMPT_FOLLOWED_BY_WEBUI_RESET :
          PROMPT_FOLLOWED_BY_WEBUI_NO_RESET);
    }
    FinishResetPromptFlow();
  }
}

void AutomaticProfileResetter::SetProgramForTesting(
    const std::string& program) {
  program_ = program;
}

void AutomaticProfileResetter::SetHashSeedForTesting(
    const std::string& hash_key) {
  hash_seed_ = hash_key;
}

void AutomaticProfileResetter::SetDelegateForTesting(
    scoped_ptr<AutomaticProfileResetterDelegate> delegate) {
  delegate_ = delegate.Pass();
}

void AutomaticProfileResetter::SetTaskRunnerForWaitingForTesting(
    const scoped_refptr<base::TaskRunner>& task_runner) {
  task_runner_for_waiting_ = task_runner;
}

void AutomaticProfileResetter::Shutdown() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  // We better not do anything substantial at this point. The metrics service
  // has already been shut down; and local state has already been commited to
  // file (in the regular fashion) for the last time.

  state_ = STATE_DISABLED;

  weak_ptr_factory_.InvalidateWeakPtrs();
  delegate_.reset();
}

void AutomaticProfileResetter::PrepareEvaluationFlow() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_INITIALIZED);

  state_ = STATE_WAITING_ON_DEPENDENCIES;

  delegate_->RequestCallbackWhenTemplateURLServiceIsLoaded(
      base::Bind(&AutomaticProfileResetter::OnTemplateURLServiceIsLoaded,
                 weak_ptr_factory_.GetWeakPtr()));
  delegate_->RequestCallbackWhenLoadedModulesAreEnumerated(
      base::Bind(&AutomaticProfileResetter::OnLoadedModulesAreEnumerated,
                 weak_ptr_factory_.GetWeakPtr()));
  delegate_->LoadTemplateURLServiceIfNeeded();
  delegate_->EnumerateLoadedModulesIfNeeded();
}

void AutomaticProfileResetter::OnTemplateURLServiceIsLoaded() {
  template_url_service_ready_ = true;
  OnDependencyIsReady();
}

void AutomaticProfileResetter::OnLoadedModulesAreEnumerated() {
  enumeration_of_loaded_modules_ready_ = true;
  OnDependencyIsReady();
}

void AutomaticProfileResetter::OnDependencyIsReady() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_WAITING_ON_DEPENDENCIES);

  if (template_url_service_ready_ && enumeration_of_loaded_modules_ready_) {
    state_ = STATE_READY;
    content::BrowserThread::PostTask(
        content::BrowserThread::UI,
        FROM_HERE,
        base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow,
                   weak_ptr_factory_.GetWeakPtr()));
  }
}

void AutomaticProfileResetter::BeginEvaluationFlow() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_READY);
  DCHECK(!program_.empty());
  DCHECK(!input_builder_);

  state_ = STATE_EVALUATING_CONDITIONS;

  input_builder_.reset(new InputBuilder(profile_, delegate_.get()));
  input_builder_->BuildEvaluatorProgramInput(
      base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow,
                 weak_ptr_factory_.GetWeakPtr()));
}

void AutomaticProfileResetter::ContinueWithEvaluationFlow(
    scoped_ptr<base::DictionaryValue> program_input) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS);

  input_builder_.reset();

  base::SequencedWorkerPool* blocking_pool =
      content::BrowserThread::GetBlockingPool();
  scoped_refptr<base::TaskRunner> task_runner =
      blocking_pool->GetTaskRunnerWithShutdownBehavior(
          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);

  base::PostTaskAndReplyWithResult(
      task_runner.get(),
      FROM_HERE,
      base::Bind(&EvaluateConditionsOnWorkerPoolThread,
                 hash_seed_,
                 program_,
                 base::Passed(&program_input)),
      base::Bind(&AutomaticProfileResetter::FinishEvaluationFlow,
                 weak_ptr_factory_.GetWeakPtr()));
}

// static
scoped_ptr<AutomaticProfileResetter::EvaluationResults>
    AutomaticProfileResetter::EvaluateConditionsOnWorkerPoolThread(
    const std::string& hash_seed,
    const std::string& program,
    scoped_ptr<base::DictionaryValue> program_input) {
  JtlInterpreter interpreter(hash_seed, program, program_input.get());
  interpreter.Execute();
  UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.InterpreterResult",
                            interpreter.result(),
                            JtlInterpreter::RESULT_MAX);

  // In each case below, the respective field in result originally contains the
  // default, so if the getter fails, we still have the correct value there.
  scoped_ptr<EvaluationResults> results(new EvaluationResults);
  interpreter.GetOutputBoolean(kHadPromptedAlreadyKey,
                               &results->had_prompted_already);
  interpreter.GetOutputString(kMementoValueInPrefsKey,
                              &results->memento_value_in_prefs);
  interpreter.GetOutputString(kMementoValueInLocalStateKey,
                              &results->memento_value_in_local_state);
  interpreter.GetOutputString(kMementoValueInFileKey,
                              &results->memento_value_in_file);
  for (size_t i = 0; i < arraysize(kCombinedStatusMaskKeys); ++i) {
    bool flag = false;
    if (interpreter.GetOutputBoolean(kCombinedStatusMaskKeys[i], &flag) && flag)
      results->combined_status_mask |= (1 << i);
  }
  for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) {
    bool flag = false;
    if (interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag) &&
        flag)
      results->satisfied_criteria_mask |= (1 << i);
  }
  return results.Pass();
}

void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask,
                                                uint32 combined_status_mask) {
  UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask",
                            satisfied_criteria_mask,
                            kSatisfiedCriteriaMaskMaximumValue);
  UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask",
                            combined_status_mask,
                            kCombinedStatusMaskMaximumValue);
}

void AutomaticProfileResetter::FinishEvaluationFlow(
    scoped_ptr<EvaluationResults> results) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS);

  ReportStatistics(results->satisfied_criteria_mask,
                   results->combined_status_mask);

  if (results->satisfied_criteria_mask != 0 && !results->had_prompted_already) {
    evaluation_results_ = results.Pass();
    BeginResetPromptFlow();
  } else {
    state_ = STATE_DONE;
  }
}

void AutomaticProfileResetter::BeginResetPromptFlow() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS);

  state_ = STATE_HAS_TRIGGERED_PROMPT;

  if (ShouldPerformLiveRun() && delegate_->TriggerPrompt()) {
    // Start fetching the brandcoded default settings speculatively in the
    // background, so as to reduce waiting time if the user chooses to go
    // through with the reset.
    delegate_->FetchBrandcodedDefaultSettingsIfNeeded();
  } else {
    PersistMementos();
    ReportPromptResult(PROMPT_NOT_TRIGGERED);
    FinishResetPromptFlow();
  }
}

void AutomaticProfileResetter::OnProfileSettingsResetCompleted() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(state_, STATE_PERFORMING_RESET);

  delegate_->DismissPrompt();
  FinishResetPromptFlow();
}

void AutomaticProfileResetter::ReportPromptResult(PromptResult result) {
  UMA_HISTOGRAM_ENUMERATION(
      "AutomaticProfileReset.PromptResult", result, PROMPT_RESULT_MAX);
}

void AutomaticProfileResetter::PersistMementos() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT ||
         state_ == STATE_HAS_SHOWN_BUBBLE);
  DCHECK(evaluation_results_);

  PreferenceHostedPromptMemento memento_in_prefs(profile_);
  LocalStateHostedPromptMemento memento_in_local_state(profile_);
  FileHostedPromptMemento memento_in_file(profile_);

  memento_in_prefs.StoreValue(evaluation_results_->memento_value_in_prefs);
  memento_in_local_state.StoreValue(
      evaluation_results_->memento_value_in_local_state);
  memento_in_file.StoreValue(evaluation_results_->memento_value_in_file);

  evaluation_results_.reset();
}

void AutomaticProfileResetter::FinishResetPromptFlow() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT ||
         state_ == STATE_HAS_SHOWN_BUBBLE ||
         state_ == STATE_PERFORMING_RESET);
  DCHECK(!evaluation_results_);

  state_ = STATE_DONE;
}
