OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/profile_resetter/automatic_profile_resetter.h" | 5 #include "chrome/browser/profile_resetter/automatic_profile_resetter.h" |
6 | 6 |
7 #include "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/prefs/pref_service.h" | 12 #include "base/prefs/pref_service.h" |
13 #include "base/strings/string_number_conversions.h" | |
13 #include "base/task_runner.h" | 14 #include "base/task_runner.h" |
14 #include "base/task_runner_util.h" | 15 #include "base/task_runner_util.h" |
15 #include "base/threading/sequenced_worker_pool.h" | 16 #include "base/threading/sequenced_worker_pool.h" |
17 #include "base/time/time.h" | |
18 #include "base/values.h" | |
19 #include "chrome/browser/browser_process.h" | |
20 #include "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h" | |
16 #include "chrome/browser/profile_resetter/jtl_interpreter.h" | 21 #include "chrome/browser/profile_resetter/jtl_interpreter.h" |
17 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
23 #include "chrome/browser/search_engines/template_url_service.h" | |
24 #include "chrome/browser/search_engines/template_url_service_factory.h" | |
18 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
19 #include "grit/browser_resources.h" | 26 #include "grit/browser_resources.h" |
20 #include "ui/base/resource/resource_bundle.h" | 27 #include "ui/base/resource/resource_bundle.h" |
21 | 28 |
22 namespace { | 29 namespace { |
Peter Kasting
2013/10/16 22:36:51
Nit: I'd just move all these down to the anonymous
engedy
2013/10/17 15:13:47
Moved down.
Cannot really move them into narrower
| |
23 | 30 |
24 // Number of bits, and maximum value (exclusive) for the mask whose bits | |
25 // indicate which of reset criteria were satisfied. | |
26 const size_t kSatisfiedCriteriaMaskBits = 2; | |
27 const uint32 kSatisfiedCriteriaMaskMaximumValue = | |
28 (1 << kSatisfiedCriteriaMaskBits); | |
29 | |
30 // Number of bits, and maximum value (exclusive) for the mask whose bits | |
31 // indicate if any of reset criteria were satisfied, and which of the mementos | |
32 // were already present. | |
33 const size_t kCombinedStatusMaskBits = 4; | |
34 const uint32 kCombinedStatusMaskMaximumValue = (1 << kCombinedStatusMaskBits); | |
35 | |
36 // Name constants for the field trial behind which we enable this feature. | 31 // Name constants for the field trial behind which we enable this feature. |
37 const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset"; | 32 const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset"; |
38 const char kAutomaticProfileResetStudyDryRunGroupName[] = "DryRun"; | 33 const char kAutomaticProfileResetStudyDryRunGroupName[] = "DryRun"; |
39 const char kAutomaticProfileResetStudyEnabledGroupName[] = "Enabled"; | 34 const char kAutomaticProfileResetStudyEnabledGroupName[] = "Enabled"; |
40 | 35 |
36 // How long to wait after start-up before unleashing the evaluation flow. | |
37 const int64 kEvaluationFlowDelayInSeconds = 55; | |
38 | |
41 // Keys used in the input dictionary of the program. | 39 // Keys used in the input dictionary of the program. |
42 // TODO(engedy): Add these here on an as-needed basis. | 40 const char kUserPreferencesKey[] = "preferences"; |
41 const char kUserPreferencesIsUserControlledKey[] = "preferences_iuc"; | |
42 const char kLocalStateKey[] = "local_state"; | |
43 const char kLocalStateIsUserControlledKey[] = "local_state_iuc"; | |
44 const char kSearchProvidersKey[] = "search_providers"; | |
45 const char kDefaultSearchProviderKey[] = "default_search_provider"; | |
46 const char kDefaultSearchProviderIsUserControlledKey[] = | |
47 "default_search_provider_iuc"; | |
48 const char kLoadedModuleDigestsKey[] = "loaded_modules"; | |
vasilii
2013/10/17 10:57:57
Alphabetical order.
engedy
2013/10/17 15:13:47
Done.
| |
43 | 49 |
44 // Keys used in the output dictionary of the program. | 50 // Keys used in the output dictionary of the program. |
45 const char kHadPromptedAlreadyKey[] = "had_prompted_already"; | 51 const char kHadPromptedAlreadyKey[] = "had_prompted_already"; |
46 const char kSatisfiedCriteriaMaskKeys[][29] = {"satisfied_criteria_mask_bit1", | 52 const char kSatisfiedCriteriaMaskKeys[][29] = {"satisfied_criteria_mask_bit1", |
47 "satisfied_criteria_mask_bit2"}; | 53 "satisfied_criteria_mask_bit2"}; |
48 const char kCombinedStatusMaskKeys[][26] = { | 54 const char kCombinedStatusMaskKeys[][26] = { |
49 "combined_status_mask_bit1", "combined_status_mask_bit2", | 55 "combined_status_mask_bit1", "combined_status_mask_bit2", |
50 "combined_status_mask_bit3", "combined_status_mask_bit4"}; | 56 "combined_status_mask_bit3", "combined_status_mask_bit4"}; |
51 | 57 |
52 // Keys used in both the input and output dictionary of the program. | 58 // Keys used in both the input and output dictionary of the program. |
53 const char kMementoValueInPrefsKey[] = "memento_value_in_prefs"; | 59 const char kMementoValueInPrefsKey[] = "memento_value_in_prefs"; |
54 const char kMementoValueInLocalStateKey[] = "memento_value_in_local_state"; | 60 const char kMementoValueInLocalStateKey[] = "memento_value_in_local_state"; |
55 const char kMementoValueInFileKey[] = "memento_value_in_file"; | 61 const char kMementoValueInFileKey[] = "memento_value_in_file"; |
56 | 62 |
57 COMPILE_ASSERT( | 63 } // namespace |
58 arraysize(kSatisfiedCriteriaMaskKeys) == kSatisfiedCriteriaMaskBits, | |
59 satisfied_criteria_mask_bits_mismatch); | |
60 COMPILE_ASSERT(arraysize(kCombinedStatusMaskKeys) == kCombinedStatusMaskBits, | |
61 combined_status_mask_bits_mismatch); | |
62 | 64 |
63 // Implementation detail classes --------------------------------------------- | 65 // AutomaticProfileResetter::EvaluationResults ------------------------------- |
64 | 66 |
65 class AutomaticProfileResetterDelegateImpl | 67 // Encapsulates the output values extracted from the evaluator program. |
66 : public AutomaticProfileResetterDelegate { | 68 struct AutomaticProfileResetter::EvaluationResults { |
67 public: | 69 EvaluationResults() |
vasilii
2013/10/17 10:57:57
Add destructor and DISALLOW_COPY_AND_ASSIGN
engedy
2013/10/17 15:13:47
I was under the impression that those are discoura
Peter Kasting
2013/10/17 19:06:14
The style guide isn't perfectly clear on this poin
engedy
2013/10/18 11:08:12
Thanks for elaborating! Then I will leave this as
| |
68 AutomaticProfileResetterDelegateImpl() {} | 70 : had_prompted_already(false), |
69 virtual ~AutomaticProfileResetterDelegateImpl() {} | 71 satisfied_criteria_mask(0), |
72 combined_status_mask(0) {} | |
70 | 73 |
71 // AutomaticProfileResetterDelegate overrides: | 74 std::string memento_value_in_prefs; |
75 std::string memento_value_in_local_state; | |
76 std::string memento_value_in_file; | |
72 | 77 |
73 virtual void ShowPrompt() OVERRIDE { | 78 bool had_prompted_already; |
74 // TODO(engedy): Call the UI from here once we have it. | 79 uint32 satisfied_criteria_mask; |
75 } | 80 uint32 combined_status_mask; |
81 }; | |
76 | 82 |
77 virtual void ReportStatistics(uint32 satisfied_criteria_mask, | 83 // AutomaticProfileResetter implementation details --------------------------- |
Peter Kasting
2013/10/16 22:36:51
Nit: Normally I just call this section "Helpers".
engedy
2013/10/17 15:13:47
Done.
| |
78 uint32 combined_status_mask) OVERRIDE { | |
79 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask", | |
80 satisfied_criteria_mask, | |
81 kSatisfiedCriteriaMaskMaximumValue); | |
82 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask", | |
83 combined_status_mask, | |
84 kCombinedStatusMaskMaximumValue); | |
85 } | |
86 | 84 |
87 private: | 85 namespace { |
88 DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterDelegateImpl); | |
89 }; | |
90 | 86 |
91 // Enumeration of the possible outcomes of showing the profile reset prompt. | 87 // Enumeration of the possible outcomes of showing the profile reset prompt. |
92 enum PromptResult { | 88 enum PromptResult { |
93 // Prompt was not shown because only a dry-run was performed. | 89 // Prompt was not shown because only a dry-run was performed. |
94 PROMPT_NOT_SHOWN, | 90 PROMPT_NOT_SHOWN, |
95 PROMPT_ACTION_RESET, | 91 PROMPT_ACTION_RESET, |
96 PROMPT_ACTION_NO_RESET, | 92 PROMPT_ACTION_NO_RESET, |
97 PROMPT_DISMISSED, | 93 PROMPT_DISMISSED, |
98 // Prompt was still shown (not dismissed by the user) when Chrome was closed. | 94 // Prompt was still shown (not dismissed by the user) when Chrome was closed. |
99 PROMPT_IGNORED, | 95 PROMPT_IGNORED, |
100 PROMPT_RESULT_MAX | 96 PROMPT_RESULT_MAX |
101 }; | 97 }; |
102 | 98 |
99 // Returns whether or not a dry-run shall be performed. | |
100 bool ShouldPerformDryRun() { | |
101 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) == | |
102 kAutomaticProfileResetStudyDryRunGroupName; | |
103 } | |
104 | |
105 // Returns whether or not a live-run shall be performed. | |
106 bool ShouldPerformLiveRun() { | |
107 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) == | |
108 kAutomaticProfileResetStudyEnabledGroupName; | |
109 } | |
110 | |
111 // Deep-copies all preferences in |source| to a sub-tree named |value_tree_key| | |
112 // in |target_dictionary|, with path expansion, and also creates an isomorphic | |
113 // sub-tree under the key |is_user_controlled_tree_key| that contains only | |
114 // Boolean values, indicating whether or not the corresponding preferences are | |
115 // coming from the 'user' PrefStore. | |
116 void BuildSubTreesFromPreferences(const PrefService* source, | |
117 const char* value_tree_key, | |
118 const char* is_user_controlled_tree_key, | |
119 base::DictionaryValue* target_dictionary) { | |
120 scoped_ptr<base::DictionaryValue> pref_name_to_value_map( | |
121 source->GetPreferenceValuesWithoutPathExpansion()); | |
122 std::vector<std::string> pref_names; | |
123 pref_names.reserve(pref_name_to_value_map->size()); | |
124 for (base::DictionaryValue::Iterator it(*pref_name_to_value_map); | |
125 !it.IsAtEnd(); it.Advance()) | |
126 pref_names.push_back(it.key()); | |
127 | |
128 base::DictionaryValue* value_tree = new base::DictionaryValue; | |
129 base::DictionaryValue* is_user_controlled_tree = new base::DictionaryValue; | |
130 for (std::vector<std::string>::const_iterator it = pref_names.begin(); | |
131 it != pref_names.end(); ++it) { | |
132 scoped_ptr<Value> pref_value_owned; | |
133 if (pref_name_to_value_map->RemoveWithoutPathExpansion(*it, | |
134 &pref_value_owned)) { | |
135 value_tree->Set(*it, pref_value_owned.release()); | |
136 const PrefService::Preference* pref = source->FindPreference(it->c_str()); | |
137 is_user_controlled_tree->Set( | |
138 *it, new base::FundamentalValue(pref->IsUserControlled())); | |
139 } | |
140 } | |
141 target_dictionary->Set(value_tree_key, value_tree); | |
142 target_dictionary->Set(is_user_controlled_tree_key, is_user_controlled_tree); | |
143 } | |
144 | |
145 // Performs the bulk of the work. Invokes the interpreter to run the |program| | |
Peter Kasting
2013/10/16 22:36:51
The bulk of what work? Invokes what interpreter?
engedy
2013/10/17 15:13:47
Yes, that is exactly what has happened. :-)
Added
| |
146 // that will evaluate whether the conditions are met for showing the reset | |
147 // prompt. The program will make this decision based on the state information | |
148 // contained in |input| in the form of key-value pairs. The program will only | |
149 // see hashed keys and values that are produced using |hash_seed| as a key. | |
150 scoped_ptr<AutomaticProfileResetter::EvaluationResults> | |
151 EvaluateConditionsOnWorkerPoolThread( | |
152 const base::StringPiece& hash_seed, | |
153 const base::StringPiece& program, | |
154 scoped_ptr<base::DictionaryValue> program_input) { | |
155 std::string hash_seed_str(hash_seed.as_string()); | |
156 std::string program_str(program.as_string()); | |
Peter Kasting
2013/10/16 22:36:51
Nit: Any particular reason to have temps for these
engedy
2013/10/17 15:13:47
None, fixed.
| |
157 JtlInterpreter interpreter(hash_seed_str, program_str, program_input.get()); | |
158 interpreter.Execute(); | |
159 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.InterpreterResult", | |
160 interpreter.result(), | |
161 JtlInterpreter::RESULT_MAX); | |
162 | |
163 // In each case below, the respective field in result originally contains the | |
164 // default, so if the getter fails, we still have the correct value there. | |
165 scoped_ptr<AutomaticProfileResetter::EvaluationResults> results( | |
166 new AutomaticProfileResetter::EvaluationResults); | |
167 interpreter.GetOutputBoolean(kHadPromptedAlreadyKey, | |
168 &results->had_prompted_already); | |
169 interpreter.GetOutputString(kMementoValueInPrefsKey, | |
170 &results->memento_value_in_prefs); | |
171 interpreter.GetOutputString(kMementoValueInLocalStateKey, | |
172 &results->memento_value_in_local_state); | |
173 interpreter.GetOutputString(kMementoValueInFileKey, | |
174 &results->memento_value_in_file); | |
175 for (size_t i = 0; i < arraysize(kCombinedStatusMaskKeys); ++i) { | |
176 bool flag = false; | |
177 if (interpreter.GetOutputBoolean(kCombinedStatusMaskKeys[i], &flag) && flag) | |
178 results->combined_status_mask |= (1 << i); | |
179 } | |
180 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) { | |
181 bool flag = false; | |
182 if (interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag) && | |
183 flag) | |
184 results->satisfied_criteria_mask |= (1 << i); | |
185 } | |
186 return results.Pass(); | |
187 } | |
188 | |
103 } // namespace | 189 } // namespace |
104 | 190 |
105 // AutomaticProfileResetter::EvaluationResults ------------------------------- | 191 // AutomaticProfileResetter -------------------------------------------------- |
106 | 192 |
107 // Encapsulates the output values extracted from the evaluator program. | 193 const size_t AutomaticProfileResetter::kSatisfiedCriteriaMaskNumberOfBits = 2u; |
108 struct AutomaticProfileResetter::EvaluationResults { | 194 const uint32 AutomaticProfileResetter::kSatisfiedCriteriaMaskMaximumValue = |
109 EvaluationResults() | 195 (1u << AutomaticProfileResetter::kSatisfiedCriteriaMaskNumberOfBits); |
110 : had_prompted_already(false), | |
111 satisfied_criteria_mask(0), | |
112 combined_status_mask(0) {} | |
113 | 196 |
114 std::string memento_value_in_prefs; | 197 const size_t AutomaticProfileResetter::kCombinedStatusMaskNumberOfBits = 4u; |
115 std::string memento_value_in_local_state; | 198 const uint32 AutomaticProfileResetter::kCombinedStatusMaskMaximumValue = |
116 std::string memento_value_in_file; | 199 (1u << AutomaticProfileResetter::kCombinedStatusMaskNumberOfBits); |
117 | 200 |
118 bool had_prompted_already; | 201 COMPILE_ASSERT(arraysize(kSatisfiedCriteriaMaskKeys) == |
119 uint32 satisfied_criteria_mask; | 202 AutomaticProfileResetter::kSatisfiedCriteriaMaskNumberOfBits, |
120 uint32 combined_status_mask; | 203 satisfied_criteria_mask_bits_mismatch); |
121 }; | 204 COMPILE_ASSERT(arraysize(kCombinedStatusMaskKeys) == |
122 | 205 AutomaticProfileResetter::kCombinedStatusMaskNumberOfBits, |
123 // AutomaticProfileResetter -------------------------------------------------- | 206 combined_status_mask_bits_mismatch); |
124 | 207 |
125 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile) | 208 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile) |
126 : profile_(profile), | 209 : profile_(profile), |
127 state_(STATE_UNINITIALIZED), | 210 state_(STATE_UNINITIALIZED), |
211 enumeration_of_loaded_modules_ready_(false), | |
212 template_url_service_ready_(false), | |
128 memento_in_prefs_(profile_), | 213 memento_in_prefs_(profile_), |
129 memento_in_local_state_(profile_), | 214 memento_in_local_state_(profile_), |
130 memento_in_file_(profile_), | 215 memento_in_file_(profile_), |
131 weak_ptr_factory_(this) { | 216 weak_ptr_factory_(this) { |
132 DCHECK(profile_); | 217 DCHECK(profile_); |
218 Initialize(); | |
133 } | 219 } |
134 | 220 |
135 AutomaticProfileResetter::~AutomaticProfileResetter() {} | 221 AutomaticProfileResetter::~AutomaticProfileResetter() {} |
136 | 222 |
137 void AutomaticProfileResetter::Initialize() { | 223 void AutomaticProfileResetter::Initialize() { |
138 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 224 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
139 DCHECK_EQ(state_, STATE_UNINITIALIZED); | 225 DCHECK_EQ(state_, STATE_UNINITIALIZED); |
140 | 226 |
141 if (ShouldPerformDryRun() || ShouldPerformLiveRun()) { | 227 if (ShouldPerformDryRun() || ShouldPerformLiveRun()) { |
142 ui::ResourceBundle& resources(ui::ResourceBundle::GetSharedInstance()); | 228 ui::ResourceBundle& resources(ui::ResourceBundle::GetSharedInstance()); |
143 if (ShouldPerformLiveRun()) { | 229 if (ShouldPerformLiveRun()) { |
144 program_ = | 230 program_ = |
145 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES); | 231 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES); |
146 hash_seed_ = | 232 hash_seed_ = |
147 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED); | 233 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED); |
148 } else { // ShouldPerformDryRun() | 234 } else { // ShouldPerformDryRun() |
149 program_ = | 235 program_ = |
150 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY); | 236 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY); |
151 hash_seed_ = resources.GetRawDataResource( | 237 hash_seed_ = resources.GetRawDataResource( |
152 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY); | 238 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY); |
153 } | 239 } |
154 delegate_.reset(new AutomaticProfileResetterDelegateImpl()); | 240 // The |template_url_service| might be NULL during unit tests. |
Peter Kasting
2013/10/16 22:36:51
Nit: This comment seems unnecessary, as this calls
engedy
2013/10/17 15:13:47
True, done.
| |
241 TemplateURLService* template_url_service = | |
242 TemplateURLServiceFactory::GetForProfile(profile_); | |
243 delegate_.reset( | |
244 new AutomaticProfileResetterDelegateImpl(template_url_service)); | |
Peter Kasting
2013/10/16 22:36:51
Nit: More compact:
delegate_.reset(new Automa
engedy
2013/10/17 15:13:47
Done.
| |
245 task_runner_for_waiting_ = | |
246 content::BrowserThread::GetMessageLoopProxyForThread( | |
247 content::BrowserThread::UI); | |
248 state_ = STATE_INITIALIZED; | |
249 } else { | |
250 state_ = STATE_DISABLED; | |
251 } | |
252 } | |
155 | 253 |
254 void AutomaticProfileResetter::Activate() { | |
255 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
256 DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED); | |
257 | |
258 if (state_ == STATE_INITIALIZED) { | |
259 if (!program_.empty()) { | |
260 // Some steps in the flow (e.g. loaded modules, file-based memento) are | |
261 // IO-intensive, so defer execution until some time later. | |
262 task_runner_for_waiting_->PostDelayedTask( | |
263 FROM_HERE, | |
264 base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow, | |
265 weak_ptr_factory_.GetWeakPtr()), | |
266 base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds)); | |
267 } else { | |
268 // Terminate early if there is no program included (nor set by tests). | |
269 state_ = STATE_DISABLED; | |
270 } | |
271 } | |
272 } | |
273 | |
274 void AutomaticProfileResetter::PrepareEvaluationFlow() { | |
275 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
276 DCHECK_EQ(state_, STATE_INITIALIZED); | |
277 | |
278 state_ = STATE_WAITING_ON_DEPENDENCIES; | |
279 | |
280 delegate_->RequestCallbackWhenTemplateURLServiceIsLoaded( | |
281 base::Bind(&AutomaticProfileResetter::OnTemplateURLServiceIsLoaded, | |
282 weak_ptr_factory_.GetWeakPtr())); | |
283 delegate_->RequestCallbackWhenLoadedModulesAreEnumerated( | |
284 base::Bind(&AutomaticProfileResetter::OnLoadedModulesAreEnumerated, | |
285 weak_ptr_factory_.GetWeakPtr())); | |
286 delegate_->LoadTemplateURLServiceIfNeeded(); | |
287 delegate_->EnumerateLoadedModulesIfNeeded(); | |
288 } | |
289 | |
290 void AutomaticProfileResetter::OnTemplateURLServiceIsLoaded() { | |
291 template_url_service_ready_ = true; | |
292 OnDependencyIsReady(); | |
293 } | |
294 | |
295 void AutomaticProfileResetter::OnLoadedModulesAreEnumerated() { | |
296 enumeration_of_loaded_modules_ready_ = true; | |
297 OnDependencyIsReady(); | |
298 } | |
299 | |
300 void AutomaticProfileResetter::OnDependencyIsReady() { | |
301 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
302 DCHECK_EQ(state_, STATE_WAITING_ON_DEPENDENCIES); | |
303 | |
304 if (template_url_service_ready_ && enumeration_of_loaded_modules_ready_) { | |
156 state_ = STATE_READY; | 305 state_ = STATE_READY; |
157 | |
158 content::BrowserThread::PostTask( | 306 content::BrowserThread::PostTask( |
159 content::BrowserThread::UI, | 307 content::BrowserThread::UI, |
160 FROM_HERE, | 308 FROM_HERE, |
161 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow, | 309 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow, |
162 weak_ptr_factory_.GetWeakPtr())); | 310 weak_ptr_factory_.GetWeakPtr())); |
163 } else { | |
164 state_ = STATE_DISABLED; | |
165 } | 311 } |
166 } | 312 } |
167 | 313 |
168 bool AutomaticProfileResetter::ShouldPerformDryRun() const { | |
169 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) == | |
170 kAutomaticProfileResetStudyDryRunGroupName; | |
171 } | |
172 | |
173 bool AutomaticProfileResetter::ShouldPerformLiveRun() const { | |
174 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) == | |
175 kAutomaticProfileResetStudyEnabledGroupName; | |
176 } | |
177 | |
178 void AutomaticProfileResetter::BeginEvaluationFlow() { | 314 void AutomaticProfileResetter::BeginEvaluationFlow() { |
179 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 315 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
180 DCHECK_EQ(state_, STATE_READY); | 316 DCHECK_EQ(state_, STATE_READY); |
317 DCHECK(!program_.empty()); | |
181 | 318 |
182 if (!program_.empty()) { | 319 state_ = STATE_WORKING; |
183 state_ = STATE_WORKING; | 320 memento_in_file_.ReadValue( |
184 memento_in_file_.ReadValue( | 321 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow, |
185 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow, | 322 weak_ptr_factory_.GetWeakPtr())); |
186 weak_ptr_factory_.GetWeakPtr())); | |
187 } else { | |
188 // Terminate early if there is no program included (nor set by tests). | |
189 state_ = STATE_DISABLED; | |
190 } | |
191 } | 323 } |
192 | 324 |
193 scoped_ptr<base::DictionaryValue> | 325 scoped_ptr<base::DictionaryValue> |
194 AutomaticProfileResetter::BuildEvaluatorProgramInput( | 326 AutomaticProfileResetter::BuildEvaluatorProgramInput( |
195 const std::string& memento_value_in_file) { | 327 const std::string& memento_value_in_file) { |
196 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 328 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
197 // TODO(engedy): Add any additional state here that is needed by the program. | 329 |
198 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue); | 330 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue); |
331 | |
332 // Include memento values (or empty strings in case mementos are not there). | |
199 input->SetString(kMementoValueInPrefsKey, memento_in_prefs_.ReadValue()); | 333 input->SetString(kMementoValueInPrefsKey, memento_in_prefs_.ReadValue()); |
200 input->SetString(kMementoValueInLocalStateKey, | 334 input->SetString(kMementoValueInLocalStateKey, |
201 memento_in_local_state_.ReadValue()); | 335 memento_in_local_state_.ReadValue()); |
202 input->SetString(kMementoValueInFileKey, memento_value_in_file); | 336 input->SetString(kMementoValueInFileKey, memento_value_in_file); |
337 | |
338 // Include all user (i.e. profile-specific) preferences, along with | |
339 // information about whether the value is coming from the 'user' PrefStore. | |
340 PrefService* prefs = profile_->GetPrefs(); | |
341 DCHECK(prefs); | |
342 BuildSubTreesFromPreferences(prefs, | |
343 kUserPreferencesKey, | |
344 kUserPreferencesIsUserControlledKey, | |
345 input.get()); | |
346 | |
347 // Include all local state (i.e. shared) preferences, along with information | |
348 // about whether the value is coming from the 'user' PrefStore. | |
349 PrefService* local_state = g_browser_process->local_state(); | |
350 DCHECK(local_state); | |
351 BuildSubTreesFromPreferences( | |
352 local_state, kLocalStateKey, kLocalStateIsUserControlledKey, input.get()); | |
353 | |
354 // Include all information related to search engines. | |
355 scoped_ptr<base::DictionaryValue> default_search_provider_details( | |
356 delegate_->GetDefaultSearchProviderDetails()); | |
357 input->Set(kDefaultSearchProviderKey, | |
358 default_search_provider_details.release()); | |
359 | |
360 scoped_ptr<base::ListValue> search_providers_details( | |
361 delegate_->GetPrepopulatedSearchProvidersDetails()); | |
362 input->Set(kSearchProvidersKey, search_providers_details.release()); | |
363 | |
364 input->SetBoolean(kDefaultSearchProviderIsUserControlledKey, | |
365 !delegate_->IsDefaultSearchProviderManaged()); | |
366 | |
367 // Include information about loaded modules. | |
368 scoped_ptr<base::ListValue> loaded_module_digests( | |
369 delegate_->GetLoadedModuleNameDigests()); | |
370 input->Set(kLoadedModuleDigestsKey, loaded_module_digests.release()); | |
371 | |
203 return input.Pass(); | 372 return input.Pass(); |
204 } | 373 } |
205 | 374 |
206 void AutomaticProfileResetter::ContinueWithEvaluationFlow( | 375 void AutomaticProfileResetter::ContinueWithEvaluationFlow( |
207 const std::string& memento_value_in_file) { | 376 const std::string& memento_value_in_file) { |
208 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 377 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
209 DCHECK_EQ(state_, STATE_WORKING); | 378 DCHECK_EQ(state_, STATE_WORKING); |
210 PrefService* prefs = profile_->GetPrefs(); | 379 PrefService* prefs = profile_->GetPrefs(); |
211 DCHECK(prefs); | 380 DCHECK(prefs); |
212 | 381 |
(...skipping 10 matching lines...) Expand all Loading... | |
223 task_runner.get(), | 392 task_runner.get(), |
224 FROM_HERE, | 393 FROM_HERE, |
225 base::Bind(&EvaluateConditionsOnWorkerPoolThread, | 394 base::Bind(&EvaluateConditionsOnWorkerPoolThread, |
226 hash_seed_, | 395 hash_seed_, |
227 program_, | 396 program_, |
228 base::Passed(&input)), | 397 base::Passed(&input)), |
229 base::Bind(&AutomaticProfileResetter::FinishEvaluationFlow, | 398 base::Bind(&AutomaticProfileResetter::FinishEvaluationFlow, |
230 weak_ptr_factory_.GetWeakPtr())); | 399 weak_ptr_factory_.GetWeakPtr())); |
231 } | 400 } |
232 | 401 |
233 // static | |
234 scoped_ptr<AutomaticProfileResetter::EvaluationResults> | |
235 AutomaticProfileResetter::EvaluateConditionsOnWorkerPoolThread( | |
236 const base::StringPiece& hash_seed, | |
237 const base::StringPiece& program, | |
238 scoped_ptr<base::DictionaryValue> program_input) { | |
239 std::string hash_seed_str(hash_seed.as_string()); | |
240 std::string program_str(program.as_string()); | |
241 JtlInterpreter interpreter(hash_seed_str, program_str, program_input.get()); | |
242 interpreter.Execute(); | |
243 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.InterpreterResult", | |
244 interpreter.result(), | |
245 JtlInterpreter::RESULT_MAX); | |
246 | |
247 // In each case below, the respective field in result originally contains the | |
248 // default, so if the getter fails, we still have the correct value there. | |
249 scoped_ptr<EvaluationResults> results(new EvaluationResults()); | |
250 interpreter.GetOutputBoolean(kHadPromptedAlreadyKey, | |
251 &results->had_prompted_already); | |
252 interpreter.GetOutputString(kMementoValueInPrefsKey, | |
253 &results->memento_value_in_prefs); | |
254 interpreter.GetOutputString(kMementoValueInLocalStateKey, | |
255 &results->memento_value_in_local_state); | |
256 interpreter.GetOutputString(kMementoValueInFileKey, | |
257 &results->memento_value_in_file); | |
258 for (size_t i = 0; i < arraysize(kCombinedStatusMaskKeys); ++i) { | |
259 bool flag = false; | |
260 if (interpreter.GetOutputBoolean(kCombinedStatusMaskKeys[i], &flag) && flag) | |
261 results->combined_status_mask |= (1 << i); | |
262 } | |
263 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) { | |
264 bool flag = false; | |
265 if (interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag) && | |
266 flag) | |
267 results->satisfied_criteria_mask |= (1 << i); | |
268 } | |
269 return results.Pass(); | |
270 } | |
271 | |
272 void AutomaticProfileResetter::FinishEvaluationFlow( | 402 void AutomaticProfileResetter::FinishEvaluationFlow( |
273 scoped_ptr<EvaluationResults> results) { | 403 scoped_ptr<EvaluationResults> results) { |
274 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 404 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
275 DCHECK_EQ(state_, STATE_WORKING); | 405 DCHECK_EQ(state_, STATE_WORKING); |
276 | 406 |
277 delegate_->ReportStatistics(results->satisfied_criteria_mask, | 407 ReportStatistics(results->satisfied_criteria_mask, |
278 results->combined_status_mask); | 408 results->combined_status_mask); |
279 | 409 |
280 if (results->satisfied_criteria_mask != 0 && !results->had_prompted_already) { | 410 if (results->satisfied_criteria_mask != 0 && !results->had_prompted_already) { |
281 memento_in_prefs_.StoreValue(results->memento_value_in_prefs); | 411 memento_in_prefs_.StoreValue(results->memento_value_in_prefs); |
282 memento_in_local_state_.StoreValue(results->memento_value_in_local_state); | 412 memento_in_local_state_.StoreValue(results->memento_value_in_local_state); |
283 memento_in_file_.StoreValue(results->memento_value_in_file); | 413 memento_in_file_.StoreValue(results->memento_value_in_file); |
284 | 414 |
285 if (ShouldPerformLiveRun()) { | 415 if (ShouldPerformLiveRun()) { |
286 delegate_->ShowPrompt(); | 416 delegate_->ShowPrompt(); |
287 } else { | 417 } else { |
288 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.PromptResult", | 418 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.PromptResult", |
289 PROMPT_NOT_SHOWN, | 419 PROMPT_NOT_SHOWN, |
290 PROMPT_RESULT_MAX); | 420 PROMPT_RESULT_MAX); |
291 } | 421 } |
292 } | 422 } |
293 | 423 |
294 state_ = STATE_DONE; | 424 state_ = STATE_DONE; |
295 } | 425 } |
296 | 426 |
427 void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask, | |
428 uint32 combined_status_mask) { | |
429 UMA_HISTOGRAM_ENUMERATION( | |
430 "AutomaticProfileReset.SatisfiedCriteriaMask", | |
431 satisfied_criteria_mask, | |
432 AutomaticProfileResetter::kSatisfiedCriteriaMaskMaximumValue); | |
433 UMA_HISTOGRAM_ENUMERATION( | |
434 "AutomaticProfileReset.CombinedStatusMask", | |
435 combined_status_mask, | |
436 AutomaticProfileResetter::kCombinedStatusMaskMaximumValue); | |
437 } | |
438 | |
297 void AutomaticProfileResetter::SetHashSeedForTesting( | 439 void AutomaticProfileResetter::SetHashSeedForTesting( |
298 const base::StringPiece& hash_key) { | 440 const base::StringPiece& hash_key) { |
299 hash_seed_ = hash_key; | 441 hash_seed_ = hash_key; |
300 } | 442 } |
301 | 443 |
302 void AutomaticProfileResetter::SetProgramForTesting( | 444 void AutomaticProfileResetter::SetProgramForTesting( |
303 const base::StringPiece& program) { | 445 const base::StringPiece& program) { |
304 program_ = program; | 446 program_ = program; |
305 } | 447 } |
306 | 448 |
307 void AutomaticProfileResetter::SetDelegateForTesting( | 449 void AutomaticProfileResetter::SetDelegateForTesting( |
308 AutomaticProfileResetterDelegate* delegate) { | 450 scoped_ptr<AutomaticProfileResetterDelegate> delegate) { |
309 delegate_.reset(delegate); | 451 delegate_ = delegate.Pass(); |
452 } | |
453 | |
454 void AutomaticProfileResetter::SetTaskRunnerForWaitingForTesting( | |
455 const scoped_refptr<base::TaskRunner>& task_runner) { | |
456 task_runner_for_waiting_ = task_runner; | |
310 } | 457 } |
311 | 458 |
312 void AutomaticProfileResetter::Shutdown() { | 459 void AutomaticProfileResetter::Shutdown() { |
313 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 460 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
314 | 461 |
315 state_ = STATE_DISABLED; | 462 state_ = STATE_DISABLED; |
316 delegate_.reset(); | 463 delegate_.reset(); |
317 weak_ptr_factory_.InvalidateWeakPtrs(); | 464 weak_ptr_factory_.InvalidateWeakPtrs(); |
318 } | 465 } |
OLD | NEW |