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

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: Created 7 years, 3 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/profiles/profile.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "grit/browser_resources.h"
18 #include "ui/base/resource/resource_bundle.h"
19
20 namespace profile_resetter {
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 kAutomaticProfileResetStudyEnabledroupName[] = "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 // Mostly trivial AutomaticProfileResetterDelegate implementation.
robertshield 2013/09/25 20:18:12 Nit: delete the above line, or explain how the imp
engedy 2013/09/27 23:27:34 Done.
65 class AutomaticProfileResetterDelegateImpl
66 : public AutomaticProfileResetterDelegate {
67 public:
68 AutomaticProfileResetterDelegateImpl() {}
69 virtual ~AutomaticProfileResetterDelegateImpl() {}
70
71 // AutomaticProfileResetterDelegate overrides:
72
73 virtual void ShowPrompt() OVERRIDE {
74 // TODO(engedy): Call the UI from here once we have it.
75 }
76
77 virtual void ReportStatistics(uint32 satisfied_criteria_mask,
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
87 private:
88 DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterDelegateImpl);
89 };
90
91 // A fake interpreter that enables writing EvaluateConditionsOnWorkerPoolThread.
robertshield 2013/09/25 20:18:12 s/enables writing/used by/ Also mention that this
engedy 2013/09/27 23:27:34 I have wired in the real thing. PTAL below.
92 class FakeInterpreter {
93 public:
94 FakeInterpreter() {}
95 ~FakeInterpreter() {}
96
97 bool GetOutputBoolean(const std::string& key, bool* target) { return false; }
98
99 bool GetOutputString(const std::string& key, std::string* target) {
100 return false;
101 }
102
103 private:
104 DISALLOW_COPY_AND_ASSIGN(FakeInterpreter);
105 };
106
107 // Enumeration of the possible outcomes of showing the profile reset prompt.
108 enum PromptResult {
109 // Prompt was not shown because only a dry-run was performed.
110 PROMPT_NOT_SHOWN,
111 PROMPT_ACTION_RESET,
112 PROMPT_ACTION_NO_RESET,
113 PROMPT_DISMISSED,
114 // Prompt was still shown (not dismissed by the user) when Chrome was closed.
115 PROMPT_IGNORED,
116 PROMPT_RESULT_MAX
117 };
118
119 } // namespace
120
121 // AutomaticProfileResetter::EvaluationResults -------------------------------
122
123 // Encapsulates the output values extracted from the evaluator program.
124 struct AutomaticProfileResetter::EvaluationResults {
125 EvaluationResults()
126 : had_prompted_already(false),
127 satisfied_criteria_mask(0),
128 combined_status_mask(0) {}
129
130 std::string memento_value_in_prefs;
131 std::string memento_value_in_local_state;
132 std::string memento_value_in_file;
133
134 bool had_prompted_already;
135 uint32 satisfied_criteria_mask;
136 uint32 combined_status_mask;
137 };
138
139 // AutomaticProfileResetter --------------------------------------------------
140
141 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile)
142 : profile_(profile),
143 state_(STATE_UNINITIALIZED),
144 memento_in_prefs_(profile_),
145 memento_in_local_state_(profile_),
146 memento_in_file_(profile_),
147 weak_ptr_factory_(this) {
148 DCHECK(profile_);
149 }
150
151 AutomaticProfileResetter::~AutomaticProfileResetter() {}
152
153 void AutomaticProfileResetter::Initialize() {
154 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
155 DCHECK_EQ(state_, STATE_UNINITIALIZED);
156
157 if (IsDryRun() || IsLiveRun()) {
158 ui::ResourceBundle& resources(ui::ResourceBundle::GetSharedInstance());
159 if (IsLiveRun()) {
160 program_ =
161 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES);
162 hash_seed_ =
163 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED);
164 } else {
165 program_ =
166 resources.GetRawDataResource(IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY);
167 hash_seed_ = resources.GetRawDataResource(
168 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY);
169 }
170 delegate_.reset(new AutomaticProfileResetterDelegateImpl());
171 state_ = STATE_READY;
172
173 content::BrowserThread::PostTask(
174 content::BrowserThread::UI,
175 FROM_HERE,
176 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow,
177 weak_ptr_factory_.GetWeakPtr()));
178 } else {
179 state_ = STATE_DISABLED;
180 }
181 }
182
183 bool AutomaticProfileResetter::IsDryRun() const {
184 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) ==
185 kAutomaticProfileResetStudyDryRunGroupName;
186 }
187
188 bool AutomaticProfileResetter::IsLiveRun() const {
189 return base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName) ==
190 kAutomaticProfileResetStudyEnabledroupName;
robertshield 2013/09/25 20:18:12 Looks like there is a G missing before the "roup"
engedy 2013/09/27 23:27:34 Done.
191 }
192
193 void AutomaticProfileResetter::BeginEvaluationFlow() {
194 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
195 DCHECK_EQ(state_, STATE_READY);
196
197 state_ = STATE_WORKING;
198
199 memento_in_file_.ReadValue(
200 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow,
201 weak_ptr_factory_.GetWeakPtr()));
202 }
203
204 scoped_ptr<base::DictionaryValue>
205 AutomaticProfileResetter::BuildEvaluatorProgramInput(
206 const std::string& memento_value_in_file) {
207 // TODO(engedy): Add any additional state that is needed here.
208 scoped_ptr<base::DictionaryValue> input(new base::DictionaryValue);
209 input->SetString(kMementoValueInPrefsKey, memento_in_prefs_.ReadValue());
210 input->SetString(kMementoValueInLocalStateKey,
211 memento_in_local_state_.ReadValue());
212 input->SetString(kMementoValueInFileKey, memento_value_in_file);
213 return input.Pass();
214 }
215
216 void AutomaticProfileResetter::ContinueWithEvaluationFlow(
217 const std::string& memento_value_in_file) {
218 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
219 DCHECK_EQ(state_, STATE_WORKING);
220 PrefService* prefs = profile_->GetPrefs();
221 DCHECK(prefs);
222
223 scoped_ptr<base::DictionaryValue> input(
224 BuildEvaluatorProgramInput(memento_value_in_file));
225
226 base::SequencedWorkerPool* blocking_pool =
227 content::BrowserThread::GetBlockingPool();
228 scoped_refptr<base::TaskRunner> task_runner =
229 blocking_pool->GetTaskRunnerWithShutdownBehavior(
230 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
231
232 base::PostTaskAndReplyWithResult(
233 task_runner.get(),
234 FROM_HERE,
235 base::Bind(&EvaluateConditionsOnWorkerPoolThread,
236 hash_seed_.as_string(),
237 program_.as_string(),
238 base::Passed(&input)),
239 base::Bind(&AutomaticProfileResetter::FinishEvaluationFlow,
240 weak_ptr_factory_.GetWeakPtr()));
241 }
242
243 scoped_ptr<AutomaticProfileResetter::EvaluationResults>
battre 2013/09/25 09:43:26 add "// static" before this line or in my opinion
engedy 2013/09/27 23:27:34 I am not sure I understand: how would this be any
244 AutomaticProfileResetter::EvaluateConditionsOnWorkerPoolThread(
245 const std::string& hash_key,
246 const std::string& program,
247 scoped_ptr<base::DictionaryValue> program_input) {
248 // TODO(engedy): Once implemented, call real interpreter from here.
249 scoped_ptr<EvaluationResults> results(new EvaluationResults());
250 FakeInterpreter interpreter;
251 interpreter.GetOutputBoolean(kHadPromptedAlreadyKey,
252 &results->had_prompted_already);
253 interpreter.GetOutputString(kMementoValueInPrefsKey,
254 &results->memento_value_in_prefs);
255 interpreter.GetOutputString(kMementoValueInLocalStateKey,
256 &results->memento_value_in_local_state);
257 interpreter.GetOutputString(kMementoValueInFileKey,
258 &results->memento_value_in_file);
259 for (size_t i = 0; i < arraysize(kCombinedStatusMaskKeys); ++i) {
260 bool flag = false; // Default value.
261 interpreter.GetOutputBoolean(kCombinedStatusMaskKeys[i], &flag);
262 if (flag)
263 results->combined_status_mask |= (1 << i);
264 }
265 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) {
266 bool flag = false; // Default value.
267 interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag);
268 if (flag)
269 results->satisfied_criteria_mask |= (1 << i);
270 }
271
272 return results.Pass();
273 }
274
275 void AutomaticProfileResetter::FinishEvaluationFlow(
276 scoped_ptr<EvaluationResults> results) {
277 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
278 DCHECK_EQ(state_, STATE_WORKING);
279
280 delegate_->ReportStatistics(results->satisfied_criteria_mask,
281 results->combined_status_mask);
282
283 if (results->satisfied_criteria_mask != 0 && !results->had_prompted_already) {
284 memento_in_prefs_.StoreValue(results->memento_value_in_prefs);
285 memento_in_local_state_.StoreValue(results->memento_value_in_local_state);
286 memento_in_file_.StoreValue(results->memento_value_in_file);
287
288 if (IsLiveRun())
289 delegate_->ShowPrompt();
290 else
robertshield 2013/09/25 20:18:12 style nit: multi line statements should be wrapped
engedy 2013/09/27 23:27:34 Done.
291 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.PromptResult",
292 PROMPT_NOT_SHOWN,
293 PROMPT_RESULT_MAX);
294 }
295
296 state_ = STATE_DONE;
297 }
298
299 void AutomaticProfileResetter::SetHashSeedForTesting(
300 const std::string& hash_key) {
301 hash_seed_ = hash_key;
battre 2013/09/25 09:43:26 This looks incorrect. If he passed hash_key parame
engedy 2013/09/25 16:56:59 Good point. I played around too much with StringPi
engedy 2013/09/27 23:27:34 Done.
302 }
303
304 void AutomaticProfileResetter::SetProgramForTesting(
305 const std::string& program) {
306 program_ = program;
307 }
308
309 void AutomaticProfileResetter::SetDelegateForTesting(
310 AutomaticProfileResetterDelegate* delegate) {
311 delegate_.reset(delegate);
312 }
313
314 void AutomaticProfileResetter::Shutdown() {
315 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
316
317 state_ = STATE_DISABLED;
318 delegate_.reset();
319 weak_ptr_factory_.InvalidateWeakPtrs();
320 }
321
322 } // namespace profile_resetter
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698