Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: chrome/browser/profile_resetter/automatic_profile_resetter.cc

Issue 24533002: Added the AutomaticProfileResetter service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments, integrated Interpreter, added unit tests. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/profile_resetter/automatic_profile_resetter.h"
6
7 #include "base/bind_helpers.h"
8 #include "base/json/json_reader.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/task_runner.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h"
15 #include "chrome/browser/profile_resetter/jtl_interpreter.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "grit/browser_resources.h"
19 #include "ui/base/resource/resource_bundle.h"
20
21 namespace {
22
23 // Number of bits, and maximum value (exclusive) for the mask consisting of
24 // flags that tell which of reset criteria were satisfied.
25 const size_t kSatisfiedCriteriaMaskBits = 2;
26 const uint32 kSatisfiedCriteriaMaskMaximumValue =
27 (1 << kSatisfiedCriteriaMaskBits);
28
29 // Number of bits, and maximum value (exclusive) for the mask consisting of
30 // flags that tell if any of reset criteria were satisfied and whether we had
31 // already shown the prompt.
32 const size_t kCombinedStatusMaskBits = 4;
33 const uint32 kCombinedStatusMaskMaximumValue = (1 << kCombinedStatusMaskBits);
34
35 // Name constants for the field trial behind which we enable this feature.
36 const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset";
37 const char kAutomaticProfileResetStudyDryRunGroupName[] = "DryRun";
38 const char kAutomaticProfileResetStudyEnabledGroupName[] = "Enabled";
39
40 // Keys used in the input dictionary of the program.
41 // TODO(engedy): Add these on an as-needed basis.
42
43 // Keys used in the output dictionary of the program.
44 const char kHadPromptedAlreadyKey[] = "had_prompted_already";
45 const char kSatisfiedCriteriaMaskKeys[][29] = {"satisfied_criteria_mask_bit1",
46 "satisfied_criteria_mask_bit2"};
47 const char kCombinedStatusMaskKeys[][26] = {
48 "combined_status_mask_bit1", "combined_status_mask_bit2",
49 "combined_status_mask_bit3", "combined_status_mask_bit4"};
50
51 // Keys used in the input *and* output dictionary of the program.
52 const char kMementoValueInPrefsKey[] = "memento_value_in_prefs";
53 const char kMementoValueInLocalStateKey[] = "memento_value_in_local_state";
54 const char kMementoValueInFileKey[] = "memento_value_in_file";
55
56 COMPILE_ASSERT(
57 arraysize(kSatisfiedCriteriaMaskKeys) == kSatisfiedCriteriaMaskBits,
58 satisfied_criteria_mask_bits_mismatch);
59 COMPILE_ASSERT(arraysize(kCombinedStatusMaskKeys) == kCombinedStatusMaskBits,
60 combined_status_mask_bits_mismatch);
61
62 // Implementation detail classes ---------------------------------------------
63
64 class AutomaticProfileResetterDelegateImpl
65 : public AutomaticProfileResetterDelegate {
66 public:
67 AutomaticProfileResetterDelegateImpl() {}
68 virtual ~AutomaticProfileResetterDelegateImpl() {}
69
70 // AutomaticProfileResetterDelegate overrides:
71
72 virtual void ShowPrompt() OVERRIDE {
73 // TODO(engedy): Call the UI from here once we have it.
74 }
75
76 virtual void ReportStatistics(uint32 satisfied_criteria_mask,
77 uint32 combined_status_mask) OVERRIDE {
78 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask",
79 satisfied_criteria_mask,
80 kSatisfiedCriteriaMaskMaximumValue);
81 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask",
82 combined_status_mask,
83 kCombinedStatusMaskMaximumValue);
84 }
85
86 private:
87 DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterDelegateImpl);
88 };
89
90 // Enumeration of the possible outcomes of showing the profile reset prompt.
91 enum PromptResult {
92 // Prompt was not shown because only a dry-run was performed.
93 PROMPT_NOT_SHOWN,
94 PROMPT_ACTION_RESET,
95 PROMPT_ACTION_NO_RESET,
96 PROMPT_DISMISSED,
97 // Prompt was still shown (not dismissed by the user) when Chrome was closed.
98 PROMPT_IGNORED,
99 PROMPT_RESULT_MAX
100 };
101
102 } // namespace
103
104 // AutomaticProfileResetter::EvaluationResults -------------------------------
105
106 // Encapsulates the output values extracted from the evaluator program.
107 struct AutomaticProfileResetter::EvaluationResults {
108 EvaluationResults()
109 : had_prompted_already(false),
110 satisfied_criteria_mask(0),
111 combined_status_mask(0) {}
112
113 std::string memento_value_in_prefs;
114 std::string memento_value_in_local_state;
115 std::string memento_value_in_file;
116
117 bool had_prompted_already;
118 uint32 satisfied_criteria_mask;
119 uint32 combined_status_mask;
120 };
121
122 // AutomaticProfileResetter --------------------------------------------------
123
124 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile)
125 : profile_(profile),
126 state_(STATE_UNINITIALIZED),
127 memento_in_prefs_(profile_),
128 memento_in_local_state_(profile_),
129 memento_in_file_(profile_),
130 weak_ptr_factory_(this) {
131 DCHECK(profile_);
132 }
133
134 AutomaticProfileResetter::~AutomaticProfileResetter() {}
135
136 void AutomaticProfileResetter::Initialize() {
137 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
138 DCHECK_EQ(state_, STATE_UNINITIALIZED);
139
140 if (ShouldPerformDryRun() || ShouldPerformLiveRun()) {
141 ui::ResourceBundle& resources(ui::ResourceBundle::GetSharedInstance());
142 if (ShouldPerformLiveRun()) {
143 program_ =
144 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES);
145 hash_seed_ =
146 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED);
147 } else { // ShouldPerformDryRun()
battre 2013/09/28 07:36:16 nit: +1 space before //
engedy 2013/10/01 14:12:19 Done.
148 program_ =
149 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY);
150 hash_seed_ = resources.GetRawDataResource(
151 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY);
152 }
153 delegate_.reset(new AutomaticProfileResetterDelegateImpl());
154
155 state_ = STATE_READY;
156
157 content::BrowserThread::PostTask(
158 content::BrowserThread::UI,
159 FROM_HERE,
160 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow,
161 weak_ptr_factory_.GetWeakPtr()));
162 } else {
163 state_ = STATE_DISABLED;
164 }
165 }
166
167 bool AutomaticProfileResetter::ShouldPerformDryRun() const {
168 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) ==
169 kAutomaticProfileResetStudyDryRunGroupName;
170 }
171
172 bool AutomaticProfileResetter::ShouldPerformLiveRun() const {
173 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) ==
174 kAutomaticProfileResetStudyEnabledGroupName;
175 }
176
177 void AutomaticProfileResetter::BeginEvaluationFlow() {
178 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
179 DCHECK_EQ(state_, STATE_READY);
180
181 state_ = STATE_WORKING;
182
183 memento_in_file_.ReadValue(
184 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow,
185 weak_ptr_factory_.GetWeakPtr()));
186 }
187
188 scoped_ptr<base::DictionaryValue>
189 AutomaticProfileResetter::BuildEvaluatorProgramInput(
190 const std::string& memento_value_in_file) {
191 // TODO(engedy): Add any additional state that is needed here.
192 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue);
193 input->SetString(kMementoValueInPrefsKey, memento_in_prefs_.ReadValue());
194 input->SetString(kMementoValueInLocalStateKey,
195 memento_in_local_state_.ReadValue());
196 input->SetString(kMementoValueInFileKey, memento_value_in_file);
197 return input.Pass();
198 }
199
200 void AutomaticProfileResetter::ContinueWithEvaluationFlow(
201 const std::string& memento_value_in_file) {
202 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
203 DCHECK_EQ(state_, STATE_WORKING);
204 PrefService* prefs = profile_->GetPrefs();
205 DCHECK(prefs);
206
207 scoped_ptr<base::DictionaryValue> input(
208 BuildEvaluatorProgramInput(memento_value_in_file));
209
210 base::SequencedWorkerPool* blocking_pool =
211 content::BrowserThread::GetBlockingPool();
212 scoped_refptr<base::TaskRunner> task_runner =
213 blocking_pool->GetTaskRunnerWithShutdownBehavior(
214 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
215
216 base::PostTaskAndReplyWithResult(
217 task_runner.get(),
218 FROM_HERE,
219 base::Bind(&EvaluateConditionsOnWorkerPoolThread,
220 hash_seed_,
221 program_,
222 base::Passed(&input)),
223 base::Bind(&AutomaticProfileResetter::FinishEvaluationFlow,
224 weak_ptr_factory_.GetWeakPtr()));
225 }
226
227 // static
228 scoped_ptr<AutomaticProfileResetter::EvaluationResults>
229 AutomaticProfileResetter::EvaluateConditionsOnWorkerPoolThread(
230 const base::StringPiece& hash_seed,
231 const base::StringPiece& program,
232 scoped_ptr<base::DictionaryValue> program_input) {
233 std::string hash_seed_str(hash_seed.as_string());
234 std::string program_str(program.as_string());
235
236 JtlInterpreter interpreter(hash_seed_str, program_str, program_input.get());
237 interpreter.Execute();
battre 2013/09/28 07:36:16 please UMA report the success status.
engedy 2013/10/01 14:12:19 Done.
238
239 scoped_ptr<EvaluationResults> results(new EvaluationResults());
240 interpreter.GetOutputBoolean(kHadPromptedAlreadyKey,
241 &results->had_prompted_already);
242 interpreter.GetOutputString(kMementoValueInPrefsKey,
243 &results->memento_value_in_prefs);
244 interpreter.GetOutputString(kMementoValueInLocalStateKey,
245 &results->memento_value_in_local_state);
246 interpreter.GetOutputString(kMementoValueInFileKey,
247 &results->memento_value_in_file);
248 for (size_t i = 0; i < arraysize(kCombinedStatusMaskKeys); ++i) {
249 bool flag = false; // Default value.
250 interpreter.GetOutputBoolean(kCombinedStatusMaskKeys[i], &flag);
251 if (flag)
252 results->combined_status_mask |= (1 << i);
253 }
254 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) {
255 bool flag = false; // Default value.
256 interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag);
257 if (flag)
258 results->satisfied_criteria_mask |= (1 << i);
259 }
260
261 return results.Pass();
262 }
263
264 void AutomaticProfileResetter::FinishEvaluationFlow(
265 scoped_ptr<EvaluationResults> results) {
266 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
267 DCHECK_EQ(state_, STATE_WORKING);
268
269 delegate_->ReportStatistics(results->satisfied_criteria_mask,
270 results->combined_status_mask);
271
272 if (results->satisfied_criteria_mask != 0 && !results->had_prompted_already) {
273 memento_in_prefs_.StoreValue(results->memento_value_in_prefs);
274 memento_in_local_state_.StoreValue(results->memento_value_in_local_state);
275 memento_in_file_.StoreValue(results->memento_value_in_file);
276
277 if (ShouldPerformLiveRun()) {
278 delegate_->ShowPrompt();
279 } else {
280 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.PromptResult",
281 PROMPT_NOT_SHOWN,
282 PROMPT_RESULT_MAX);
283 }
284 }
285
286 state_ = STATE_DONE;
287 }
288
289 void AutomaticProfileResetter::SetHashSeedForTesting(
290 const base::StringPiece& hash_key) {
291 hash_seed_ = hash_key;
292 }
293
294 void AutomaticProfileResetter::SetProgramForTesting(
295 const base::StringPiece& program) {
296 program_ = program;
297 }
298
299 void AutomaticProfileResetter::SetDelegateForTesting(
300 AutomaticProfileResetterDelegate* delegate) {
301 delegate_.reset(delegate);
302 }
303
304 void AutomaticProfileResetter::Shutdown() {
305 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
306
307 state_ = STATE_DISABLED;
308 delegate_.reset();
309 weak_ptr_factory_.InvalidateWeakPtrs();
310 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698