14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/profile_resetter/automatic_profile_resetter.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/bind.h"
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/bind_helpers.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/ref_counted.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/metrics/field_trial.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/metrics/histogram.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/sparse_histogram.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/prefs/pref_service.h"
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/string_util.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/task_runner.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/task_runner_util.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/time/time.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/timer/elapsed_timer.h"
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/values.h"
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/browser_process.h"
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h"
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/profile_resetter/jtl_interpreter.h"
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service.h"
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service_factory.h"
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/variations/variations_associated_data.h"
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "grit/browser_resources.h"
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Helpers -------------------------------------------------------------------
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace {
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Name constants for the field trial behind which we enable this feature.
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset";
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kAutomaticProfileResetStudyDryRunGroupName[] = "DryRun";
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kAutomaticProfileResetStudyEnabledGroupName[] = "Enabled";
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kAutomaticProfileResetStudyProgramParameterName[] = "program";
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kAutomaticProfileResetStudyHashSeedParameterName[] = "hash_seed";
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// How long to wait after start-up before unleashing the evaluation flow.
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int64 kEvaluationFlowDelayInSeconds = 55;
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Keys used in the input dictionary of the program.
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kDefaultSearchProviderKey[] = "default_search_provider";
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kDefaultSearchProviderIsUserControlledKey[] =
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    "default_search_provider_iuc";
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kLoadedModuleDigestsKey[] = "loaded_modules";
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kLocalStateKey[] = "local_state";
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kLocalStateIsUserControlledKey[] = "local_state_iuc";
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kSearchProvidersKey[] = "search_providers";
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kUserPreferencesKey[] = "preferences";
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kUserPreferencesIsUserControlledKey[] = "preferences_iuc";
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Keys used in the output dictionary of the program.
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kCombinedStatusMaskKeyPrefix[] = "combined_status_mask_bit";
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kHadPromptedAlreadyKey[] = "had_prompted_already";
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kShouldPromptKey[] = "should_prompt";
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kSatisfiedCriteriaMaskKeyPrefix[] = "satisfied_criteria_mask_bit";
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Keys used in both the input and output dictionary of the program.
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kMementoValueInFileKey[] = "memento_value_in_file";
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kMementoValueInLocalStateKey[] = "memento_value_in_local_state";
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char kMementoValueInPrefsKey[] = "memento_value_in_prefs";
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Number of bits, and maximum value (exclusive) for the mask whose bits
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// indicate which of reset criteria were satisfied.
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const size_t kSatisfiedCriteriaMaskNumberOfBits = 5u;
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const uint32 kSatisfiedCriteriaMaskMaximumValue =
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    (1u << kSatisfiedCriteriaMaskNumberOfBits);
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Number of bits, and maximum value (exclusive) for the mask whose bits
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// indicate if any of reset criteria were satisfied, and which of the mementos
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// were already present.
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const size_t kCombinedStatusMaskNumberOfBits = 4u;
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const uint32 kCombinedStatusMaskMaximumValue =
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    (1u << kCombinedStatusMaskNumberOfBits);
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Returns whether or not a dry-run shall be performed.
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ShouldPerformDryRun() {
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return StartsWithASCII(
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName),
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kAutomaticProfileResetStudyDryRunGroupName, true);
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Returns whether or not a live-run shall be performed.
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ShouldPerformLiveRun() {
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return StartsWithASCII(
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName),
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kAutomaticProfileResetStudyEnabledGroupName, true);
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// If the currently active experiment group prescribes a |program| and
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// |hash_seed| to use instead of the baked-in ones, retrieves those and returns
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// true. Otherwise, returns false.
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool GetProgramAndHashSeedOverridesFromExperiment(std::string* program,
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                  std::string* hash_seed) {
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(program);
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(hash_seed);
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD)
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::map<std::string, std::string> params;
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  chrome_variations::GetVariationParams(kAutomaticProfileResetStudyName,
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        &params);
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (params.count(kAutomaticProfileResetStudyProgramParameterName) &&
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      params.count(kAutomaticProfileResetStudyHashSeedParameterName)) {
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    program->swap(params[kAutomaticProfileResetStudyProgramParameterName]);
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hash_seed->swap(params[kAutomaticProfileResetStudyHashSeedParameterName]);
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Takes |pref_name_to_value_map|, which shall be a deep-copy of all preferences
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// in |source| without path expansion; and (1.) creates a sub-tree from it named
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// |value_tree_key| in |target_dictionary| with path expansion, and (2.) also
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// creates an isomorphic sub-tree under the key |is_user_controlled_tree_key|
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// that contains only Boolean values indicating whether or not the corresponding
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// preference is coming from the 'user' PrefStore.
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void BuildSubTreesFromPreferences(
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> pref_name_to_value_map,
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const PrefService* source,
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char* value_tree_key,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char* is_user_controlled_tree_key,
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DictionaryValue* target_dictionary) {
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<std::string> pref_names;
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  pref_names.reserve(pref_name_to_value_map->size());
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (base::DictionaryValue::Iterator it(*pref_name_to_value_map);
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       !it.IsAtEnd(); it.Advance())
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pref_names.push_back(it.key());
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::DictionaryValue* value_tree = new base::DictionaryValue;
1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::DictionaryValue* is_user_controlled_tree = new base::DictionaryValue;
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (std::vector<std::string>::const_iterator it = pref_names.begin();
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       it != pref_names.end(); ++it) {
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::Value> pref_value_owned;
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (pref_name_to_value_map->RemoveWithoutPathExpansion(*it,
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                           &pref_value_owned)) {
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_tree->Set(*it, pref_value_owned.release());
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const PrefService::Preference* pref = source->FindPreference(it->c_str());
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      is_user_controlled_tree->Set(
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          *it, new base::FundamentalValue(pref->IsUserControlled()));
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  target_dictionary->Set(value_tree_key, value_tree);
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  target_dictionary->Set(is_user_controlled_tree_key, is_user_controlled_tree);
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// AutomaticProfileResetter::InputBuilder ------------------------------------
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Collects all the information that is required by the evaluator program to
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// assess whether or not the conditions for showing the reset prompt are met.
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// This necessitates a lot of work that has to be performed on the UI thread,
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// such as: accessing the Preferences, Local State, and TemplateURLService.
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// In order to keep the browser responsive, the UI thread shall not be blocked
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// for long consecutive periods of time. Unfortunately, we cannot reduce the
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// total amount of work. Instead, what this class does is to split the work into
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// shorter tasks that are posted one-at-a-time to the UI thread in a serial
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// fashion, so as to give a chance to run other tasks that have accumulated in
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// the meantime.
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class AutomaticProfileResetter::InputBuilder
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : public base::SupportsWeakPtr<InputBuilder> {
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)>
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ProgramInputCallback;
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The dependencies must have been initialized through |delegate|, i.e. the
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // RequestCallback[...] methods must have already fired before calling this.
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InputBuilder(Profile* profile, AutomaticProfileResetterDelegate* delegate)
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : profile_(profile),
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        delegate_(delegate),
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        memento_in_prefs_(profile_),
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        memento_in_local_state_(profile_),
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        memento_in_file_(profile_) {}
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ~InputBuilder() {}
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Assembles the data required by the evaluator program into a dictionary
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // format, and posts it back to the UI thread with |callback| once ready. In
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // order not to block the UI thread for long consecutive periods of time, the
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // work is divided into smaller tasks, see class comment above for details.
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // It is safe to destroy |this| immediately from within the |callback|.
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void BuildEvaluatorProgramInput(const ProgramInputCallback& callback) {
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(!data_);
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(!callback.is_null());
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_.reset(new base::DictionaryValue);
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    callback_ = callback;
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AddAsyncTask(base::Bind(&InputBuilder::IncludeMementoValues, AsWeakPtr()));
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AddTask(base::Bind(&InputBuilder::IncludeUserPreferences, AsWeakPtr()));
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AddTask(base::Bind(&InputBuilder::IncludeLocalState, AsWeakPtr()));
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AddTask(base::Bind(&InputBuilder::IncludeSearchEngines, AsWeakPtr()));
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AddTask(base::Bind(&InputBuilder::IncludeLoadedModules, AsWeakPtr()));
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Each task will post the next one. Just trigger the chain reaction.
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PostNextTask();
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Asynchronous task that includes memento values (or empty strings in case
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // mementos are not there).
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncludeMementoValues() {
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_->SetString(kMementoValueInPrefsKey, memento_in_prefs_.ReadValue());
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_->SetString(kMementoValueInLocalStateKey,
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     memento_in_local_state_.ReadValue());
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    memento_in_file_.ReadValue(base::Bind(
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        &InputBuilder::IncludeFileBasedMementoCallback, AsWeakPtr()));
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called back by |memento_in_file_| once the |memento_value| has been read.
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncludeFileBasedMementoCallback(const std::string& memento_value) {
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_->SetString(kMementoValueInFileKey, memento_value);
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // As an asynchronous task, we need to take care of posting the next task.
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PostNextTask();
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Task that includes all user (i.e. profile-specific) preferences, along with
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // information about whether the value is coming from the 'user' PrefStore.
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This is the most expensive operation, so it is itself split into two parts.
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncludeUserPreferences() {
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PrefService* prefs = profile_->GetPrefs();
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(prefs);
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> pref_name_to_value_map(
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        prefs->GetPreferenceValuesWithoutPathExpansion());
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AddTask(base::Bind(&InputBuilder::IncludeUserPreferencesPartTwo,
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       AsWeakPtr(),
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       base::Passed(&pref_name_to_value_map)));
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Second part to above.
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncludeUserPreferencesPartTwo(
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      scoped_ptr<base::DictionaryValue> pref_name_to_value_map) {
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PrefService* prefs = profile_->GetPrefs();
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(prefs);
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BuildSubTreesFromPreferences(
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        pref_name_to_value_map.Pass(),
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        prefs,
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        kUserPreferencesKey,
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        kUserPreferencesIsUserControlledKey,
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        data_.get());
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Task that includes all local state (i.e. shared) preferences, along with
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // information about whether the value is coming from the 'user' PrefStore.
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncludeLocalState() {
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PrefService* local_state = g_browser_process->local_state();
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(local_state);
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> pref_name_to_value_map(
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        local_state->GetPreferenceValuesWithoutPathExpansion());
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BuildSubTreesFromPreferences(
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        pref_name_to_value_map.Pass(),
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        local_state,
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        kLocalStateKey,
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        kLocalStateIsUserControlledKey,
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        data_.get());
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Task that includes all information related to search engines.
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncludeSearchEngines() {
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> default_search_provider_details(
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        delegate_->GetDefaultSearchProviderDetails());
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_->Set(kDefaultSearchProviderKey,
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               default_search_provider_details.release());
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::ListValue> search_providers_details(
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        delegate_->GetPrepopulatedSearchProvidersDetails());
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_->Set(kSearchProvidersKey, search_providers_details.release());
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_->SetBoolean(kDefaultSearchProviderIsUserControlledKey,
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      !delegate_->IsDefaultSearchProviderManaged());
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Task that includes information about loaded modules.
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncludeLoadedModules() {
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::ListValue> loaded_module_digests(
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        delegate_->GetLoadedModuleNameDigests());
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    data_->Set(kLoadedModuleDigestsKey, loaded_module_digests.release());
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // -------------------------------------------------------------------------
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Adds a |task| that can do as much asynchronous processing as it wants, but
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // will need to finally call PostNextTask() on the UI thread when done.
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void AddAsyncTask(const base::Closure& task) {
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    task_queue_.push(task);
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Convenience wrapper for synchronous tasks.
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void SynchronousTaskWrapper(const base::Closure& task) {
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ElapsedTimer timer;
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    task.Run();
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        "AutomaticProfileReset.InputBuilder.TaskDuration",
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        timer.Elapsed(),
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(1),
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::TimeDelta::FromSeconds(2),
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        50);
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PostNextTask();
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Adds a task that needs to finish synchronously. In exchange, PostNextTask()
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // is called automatically when the |task| returns, and execution time is
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // measured.
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void AddTask(const base::Closure& task) {
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    task_queue_.push(
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::Bind(&InputBuilder::SynchronousTaskWrapper, AsWeakPtr(), task));
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Posts the next task from the |task_queue_|, unless it is exhausted, in
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // which case it posts |callback_| to return with the results.
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void PostNextTask() {
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::Closure next_task;
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (task_queue_.empty()) {
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      next_task = base::Bind(callback_, base::Passed(&data_));
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      next_task = task_queue_.front();
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      task_queue_.pop();
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::BrowserThread::PostTask(
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        content::BrowserThread::UI, FROM_HERE, next_task);
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Profile* profile_;
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AutomaticProfileResetterDelegate* delegate_;
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ProgramInputCallback callback_;
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PreferenceHostedPromptMemento memento_in_prefs_;
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  LocalStateHostedPromptMemento memento_in_local_state_;
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FileHostedPromptMemento memento_in_file_;
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> data_;
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::queue<base::Closure> task_queue_;
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(InputBuilder);
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// AutomaticProfileResetter::EvaluationResults -------------------------------
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Encapsulates the output values extracted from the evaluator program.
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct AutomaticProfileResetter::EvaluationResults {
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EvaluationResults()
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : should_prompt(false),
355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        had_prompted_already(false),
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        satisfied_criteria_mask(0),
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        combined_status_mask(0) {}
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string memento_value_in_prefs;
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string memento_value_in_local_state;
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string memento_value_in_file;
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool should_prompt;
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool had_prompted_already;
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  uint32 satisfied_criteria_mask;
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  uint32 combined_status_mask;
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// AutomaticProfileResetter --------------------------------------------------
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile)
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : profile_(profile),
3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      state_(STATE_UNINITIALIZED),
3751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      enumeration_of_loaded_modules_ready_(false),
3761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      template_url_service_ready_(false),
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      has_already_dismissed_prompt_(false),
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      should_show_reset_banner_(false),
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(profile_);
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)AutomaticProfileResetter::~AutomaticProfileResetter() {}
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::Initialize() {
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_UNINITIALIZED);
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ShouldPerformDryRun() && !ShouldPerformLiveRun()) {
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    state_ = STATE_DISABLED;
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!GetProgramAndHashSeedOverridesFromExperiment(&program_, &hash_seed_)) {
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ui::ResourceBundle& resources(ui::ResourceBundle::GetSharedInstance());
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (ShouldPerformLiveRun()) {
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      program_ = resources.GetRawDataResource(
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IDR_AUTOMATIC_PROFILE_RESET_RULES).as_string();
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      hash_seed_ = resources.GetRawDataResource(
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED).as_string();
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {  // ShouldPerformDryRun()
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      program_ = resources.GetRawDataResource(
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY).as_string();
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      hash_seed_ = resources.GetRawDataResource(
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY).as_string();
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_.reset(new AutomaticProfileResetterDelegateImpl(
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      profile_, ProfileResetter::ALL));
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  task_runner_for_waiting_ =
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      content::BrowserThread::GetMessageLoopProxyForThread(
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          content::BrowserThread::UI);
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = STATE_INITIALIZED;
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::Activate() {
4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
4201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED);
4211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (state_ == STATE_INITIALIZED) {
4231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!program_.empty()) {
4241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Some steps in the flow (e.g. loaded modules, file-based memento) are
4251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // IO-intensive, so defer execution until some time later.
4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      task_runner_for_waiting_->PostDelayedTask(
4271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          FROM_HERE,
4281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow,
4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()),
4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds));
4311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
4321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Terminate early if there is no program included (nor set by tests).
4331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      state_ = STATE_DISABLED;
4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::TriggerProfileReset(bool send_feedback) {
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE);
441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = STATE_PERFORMING_RESET;
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  should_show_reset_banner_ = false;
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReportPromptResult(PROMPT_ACTION_RESET);
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_->TriggerProfileSettingsReset(
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      send_feedback,
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&AutomaticProfileResetter::OnProfileSettingsResetCompleted,
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::SkipProfileReset() {
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE);
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  should_show_reset_banner_ = false;
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReportPromptResult(PROMPT_ACTION_NO_RESET);
459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_->DismissPrompt();
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FinishResetPromptFlow();
461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool AutomaticProfileResetter::IsResetPromptFlowActive() const {
464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return state_ == STATE_HAS_TRIGGERED_PROMPT ||
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      state_ == STATE_HAS_SHOWN_BUBBLE;
466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AutomaticProfileResetter::ShouldShowResetBanner() const {
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return should_show_reset_banner_ && ShouldPerformLiveRun();
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::NotifyDidShowResetBubble() {
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_HAS_TRIGGERED_PROMPT);
476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
477f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = STATE_HAS_SHOWN_BUBBLE;
478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PersistMementos();
480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReportPromptResult(PROMPT_SHOWN_BUBBLE);
481f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
482f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::NotifyDidOpenWebUIResetDialog() {
484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This notification is invoked unconditionally by the WebUI, only care about
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // it when the prompt flow is currently active (and not yet resetting).
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (state_ == STATE_HAS_TRIGGERED_PROMPT ||
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      state_ == STATE_HAS_SHOWN_BUBBLE) {
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_already_dismissed_prompt_ = true;
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_->DismissPrompt();
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::NotifyDidCloseWebUIResetDialog(
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool performed_reset) {
497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
499f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This notification is invoked unconditionally by the WebUI, only care about
500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // it when the prompt flow is currently active (and not yet resetting).
501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (state_ == STATE_HAS_TRIGGERED_PROMPT ||
502f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      state_ == STATE_HAS_SHOWN_BUBBLE) {
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!has_already_dismissed_prompt_)
504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      delegate_->DismissPrompt();
505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (state_ == STATE_HAS_TRIGGERED_PROMPT) {
506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      PersistMementos();
507f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ReportPromptResult(performed_reset ?
508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_RESET :
509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_NO_RESET);
510f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {  // if (state_ == STATE_HAS_SHOWN_PROMPT)
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ReportPromptResult(performed_reset ?
512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          PROMPT_FOLLOWED_BY_WEBUI_RESET :
513f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          PROMPT_FOLLOWED_BY_WEBUI_NO_RESET);
514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FinishResetPromptFlow();
516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AutomaticProfileResetter::NotifyDidCloseWebUIResetBanner() {
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  should_show_reset_banner_ = false;
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::SetProgramForTesting(
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& program) {
5261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  program_ = program;
5271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::SetHashSeedForTesting(
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& hash_key) {
531f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hash_seed_ = hash_key;
532f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
533f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::SetDelegateForTesting(
5351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<AutomaticProfileResetterDelegate> delegate) {
5361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_ = delegate.Pass();
5371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::SetTaskRunnerForWaitingForTesting(
5401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const scoped_refptr<base::TaskRunner>& task_runner) {
5411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  task_runner_for_waiting_ = task_runner;
5421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
544f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::Shutdown() {
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
547f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We better not do anything substantial at this point. The metrics service
548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // has already been shut down; and local state has already been commited to
549f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // file (in the regular fashion) for the last time.
550f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
551f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = STATE_DISABLED;
552f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
553f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
554f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_.reset();
5551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::PrepareEvaluationFlow() {
5581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
5591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_EQ(state_, STATE_INITIALIZED);
5601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  state_ = STATE_WAITING_ON_DEPENDENCIES;
5621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_->RequestCallbackWhenTemplateURLServiceIsLoaded(
5641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      base::Bind(&AutomaticProfileResetter::OnTemplateURLServiceIsLoaded,
5651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
5661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_->RequestCallbackWhenLoadedModulesAreEnumerated(
5671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      base::Bind(&AutomaticProfileResetter::OnLoadedModulesAreEnumerated,
5681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
5691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_->LoadTemplateURLServiceIfNeeded();
5701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_->EnumerateLoadedModulesIfNeeded();
5711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::OnTemplateURLServiceIsLoaded() {
5741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  template_url_service_ready_ = true;
5751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OnDependencyIsReady();
5761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::OnLoadedModulesAreEnumerated() {
5791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  enumeration_of_loaded_modules_ready_ = true;
5801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OnDependencyIsReady();
5811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AutomaticProfileResetter::OnDependencyIsReady() {
5841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
5851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_EQ(state_, STATE_WAITING_ON_DEPENDENCIES);
5864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (template_url_service_ready_ && enumeration_of_loaded_modules_ready_) {
5881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    state_ = STATE_READY;
5894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    content::BrowserThread::PostTask(
5904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        content::BrowserThread::UI,
5914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        FROM_HERE,
5924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow,
5934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
5944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AutomaticProfileResetter::BeginEvaluationFlow() {
5984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
5994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(state_, STATE_READY);
6001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!program_.empty());
601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!input_builder_);
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = STATE_EVALUATING_CONDITIONS;
6044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  input_builder_.reset(new InputBuilder(profile_, delegate_.get()));
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  input_builder_->BuildEvaluatorProgramInput(
6071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow,
6081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
6094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AutomaticProfileResetter::ContinueWithEvaluationFlow(
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> program_input) {
6134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS);
6154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  input_builder_.reset();
6174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::SequencedWorkerPool* blocking_pool =
6194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      content::BrowserThread::GetBlockingPool();
6204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<base::TaskRunner> task_runner =
6214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      blocking_pool->GetTaskRunnerWithShutdownBehavior(
6224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
6234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      task_runner.get(),
6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE,
6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&EvaluateConditionsOnWorkerPoolThread,
6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 hash_seed_,
6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 program_,
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 base::Passed(&program_input)),
6314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&AutomaticProfileResetter::FinishEvaluationFlow,
6324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
6334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static
6364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)scoped_ptr<AutomaticProfileResetter::EvaluationResults>
6371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    AutomaticProfileResetter::EvaluateConditionsOnWorkerPoolThread(
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& hash_seed,
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& program,
6404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> program_input) {
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  JtlInterpreter interpreter(hash_seed, program, program_input.get());
6424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  interpreter.Execute();
6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.InterpreterResult",
6444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            interpreter.result(),
6454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            JtlInterpreter::RESULT_MAX);
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_SPARSE_SLOWLY("AutomaticProfileReset.ProgramChecksum",
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              interpreter.CalculateProgramChecksum());
6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // In each case below, the respective field in result originally contains the
6504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // default, so if the getter fails, we still have the correct value there.
6511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<EvaluationResults> results(new EvaluationResults);
652a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  interpreter.GetOutputBoolean(kShouldPromptKey, &results->should_prompt);
6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  interpreter.GetOutputBoolean(kHadPromptedAlreadyKey,
6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               &results->had_prompted_already);
6554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  interpreter.GetOutputString(kMementoValueInPrefsKey,
6564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                              &results->memento_value_in_prefs);
6574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  interpreter.GetOutputString(kMementoValueInLocalStateKey,
6584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                              &results->memento_value_in_local_state);
6594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  interpreter.GetOutputString(kMementoValueInFileKey,
6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                              &results->memento_value_in_file);
661a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < kCombinedStatusMaskNumberOfBits; ++i) {
6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    bool flag = false;
663a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string mask_i_th_bit_key =
664a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        kCombinedStatusMaskKeyPrefix + base::IntToString(i + 1);
665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (interpreter.GetOutputBoolean(mask_i_th_bit_key, &flag) && flag)
6664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      results->combined_status_mask |= (1 << i);
6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
668a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < kSatisfiedCriteriaMaskNumberOfBits; ++i) {
6694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    bool flag = false;
670a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string mask_i_th_bit_key =
671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        kSatisfiedCriteriaMaskKeyPrefix + base::IntToString(i + 1);
672a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (interpreter.GetOutputBoolean(mask_i_th_bit_key, &flag) && flag)
6734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      results->satisfied_criteria_mask |= (1 << i);
6744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return results.Pass();
6764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
6774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
678f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask,
679f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                uint32 combined_status_mask) {
680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask",
681f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            satisfied_criteria_mask,
682f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            kSatisfiedCriteriaMaskMaximumValue);
683f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask",
684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            combined_status_mask,
685f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            kCombinedStatusMaskMaximumValue);
686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AutomaticProfileResetter::FinishEvaluationFlow(
6894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<EvaluationResults> results) {
6904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
691f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS);
6924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ReportStatistics(results->satisfied_criteria_mask,
6941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                   results->combined_status_mask);
6954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (results->should_prompt)
6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    should_show_reset_banner_ = true;
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (results->should_prompt && !results->had_prompted_already) {
700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    evaluation_results_ = results.Pass();
701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BeginResetPromptFlow();
702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    state_ = STATE_DONE;
704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
705f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
7064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::BeginResetPromptFlow() {
708f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
709f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS);
710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = STATE_HAS_TRIGGERED_PROMPT;
712f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
713f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (ShouldPerformLiveRun() && delegate_->TriggerPrompt()) {
714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Start fetching the brandcoded default settings speculatively in the
715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // background, so as to reduce waiting time if the user chooses to go
716f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // through with the reset.
717f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delegate_->FetchBrandcodedDefaultSettingsIfNeeded();
718f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
719f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PersistMementos();
720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ReportPromptResult(PROMPT_NOT_TRIGGERED);
721f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FinishResetPromptFlow();
7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
723f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
7244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::OnProfileSettingsResetCompleted() {
726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
727f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, STATE_PERFORMING_RESET);
728f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
729f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_->DismissPrompt();
730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FinishResetPromptFlow();
7314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
7324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::ReportPromptResult(PromptResult result) {
734f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "AutomaticProfileReset.PromptResult", result, PROMPT_RESULT_MAX);
7364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
7374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
738f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::PersistMementos() {
7394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT ||
741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ == STATE_HAS_SHOWN_BUBBLE);
742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(evaluation_results_);
7434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PreferenceHostedPromptMemento memento_in_prefs(profile_);
745f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  LocalStateHostedPromptMemento memento_in_local_state(profile_);
746f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FileHostedPromptMemento memento_in_file(profile_);
747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
748f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  memento_in_prefs.StoreValue(evaluation_results_->memento_value_in_prefs);
749f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  memento_in_local_state.StoreValue(
750f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      evaluation_results_->memento_value_in_local_state);
751f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  memento_in_file.StoreValue(evaluation_results_->memento_value_in_file);
752f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
753f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  evaluation_results_.reset();
754f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
755f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
756f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AutomaticProfileResetter::FinishResetPromptFlow() {
757f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
758f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT ||
759f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ == STATE_HAS_SHOWN_BUBBLE ||
760f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ == STATE_PERFORMING_RESET);
761f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!evaluation_results_);
762f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
763f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = STATE_DONE;
7644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
765