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.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
100 const uint32 kCombinedStatusMaskMaximumValue = | 100 const uint32 kCombinedStatusMaskMaximumValue = |
101 (1u << kCombinedStatusMaskNumberOfBits); | 101 (1u << kCombinedStatusMaskNumberOfBits); |
102 | 102 |
103 COMPILE_ASSERT( | 103 COMPILE_ASSERT( |
104 arraysize(kSatisfiedCriteriaMaskKeys) == kSatisfiedCriteriaMaskNumberOfBits, | 104 arraysize(kSatisfiedCriteriaMaskKeys) == kSatisfiedCriteriaMaskNumberOfBits, |
105 satisfied_criteria_mask_bits_mismatch); | 105 satisfied_criteria_mask_bits_mismatch); |
106 COMPILE_ASSERT( | 106 COMPILE_ASSERT( |
107 arraysize(kCombinedStatusMaskKeys) == kCombinedStatusMaskNumberOfBits, | 107 arraysize(kCombinedStatusMaskKeys) == kCombinedStatusMaskNumberOfBits, |
108 combined_status_mask_bits_mismatch); | 108 combined_status_mask_bits_mismatch); |
109 | 109 |
110 // Enumeration of the possible outcomes of showing the profile reset prompt. | |
111 enum PromptResult { | |
112 // Prompt was not shown because only a dry-run was performed. | |
113 PROMPT_NOT_SHOWN, | |
114 PROMPT_ACTION_RESET, | |
115 PROMPT_ACTION_NO_RESET, | |
116 PROMPT_DISMISSED, | |
117 // Prompt was still shown (not dismissed by the user) when Chrome was closed. | |
118 PROMPT_IGNORED, | |
119 PROMPT_RESULT_MAX | |
120 }; | |
121 | |
122 // Returns whether or not a dry-run shall be performed. | 110 // Returns whether or not a dry-run shall be performed. |
123 bool ShouldPerformDryRun() { | 111 bool ShouldPerformDryRun() { |
124 return StartsWithASCII( | 112 return StartsWithASCII( |
125 base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName), | 113 base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName), |
126 kAutomaticProfileResetStudyDryRunGroupName, true); | 114 kAutomaticProfileResetStudyDryRunGroupName, true); |
127 } | 115 } |
128 | 116 |
129 // Returns whether or not a live-run shall be performed. | 117 // Returns whether or not a live-run shall be performed. |
130 bool ShouldPerformLiveRun() { | 118 bool ShouldPerformLiveRun() { |
131 return StartsWithASCII( | 119 return StartsWithASCII( |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 } // namespace | 172 } // namespace |
185 | 173 |
186 | 174 |
187 // AutomaticProfileResetter -------------------------------------------------- | 175 // AutomaticProfileResetter -------------------------------------------------- |
188 | 176 |
189 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile) | 177 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile) |
190 : profile_(profile), | 178 : profile_(profile), |
191 state_(STATE_UNINITIALIZED), | 179 state_(STATE_UNINITIALIZED), |
192 enumeration_of_loaded_modules_ready_(false), | 180 enumeration_of_loaded_modules_ready_(false), |
193 template_url_service_ready_(false), | 181 template_url_service_ready_(false), |
182 has_shown_bubble_(false), | |
194 memento_in_prefs_(profile_), | 183 memento_in_prefs_(profile_), |
195 memento_in_local_state_(profile_), | 184 memento_in_local_state_(profile_), |
196 memento_in_file_(profile_), | 185 memento_in_file_(profile_), |
197 weak_ptr_factory_(this) { | 186 weak_ptr_factory_(this) { |
198 DCHECK(profile_); | 187 DCHECK(profile_); |
199 } | 188 } |
200 | 189 |
201 AutomaticProfileResetter::~AutomaticProfileResetter() {} | 190 AutomaticProfileResetter::~AutomaticProfileResetter() {} |
202 | 191 |
203 void AutomaticProfileResetter::Initialize() { | 192 void AutomaticProfileResetter::Initialize() { |
(...skipping 18 matching lines...) Expand all Loading... | |
222 IDR_AUTOMATIC_PROFILE_RESET_RULES).as_string(); | 211 IDR_AUTOMATIC_PROFILE_RESET_RULES).as_string(); |
223 hash_seed_ = resources.GetRawDataResource( | 212 hash_seed_ = resources.GetRawDataResource( |
224 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED).as_string(); | 213 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED).as_string(); |
225 } else { // ShouldPerformDryRun() | 214 } else { // ShouldPerformDryRun() |
226 program_ = resources.GetRawDataResource( | 215 program_ = resources.GetRawDataResource( |
227 IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY).as_string(); | 216 IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY).as_string(); |
228 hash_seed_ = resources.GetRawDataResource( | 217 hash_seed_ = resources.GetRawDataResource( |
229 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY).as_string(); | 218 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY).as_string(); |
230 } | 219 } |
231 | 220 |
232 delegate_.reset(new AutomaticProfileResetterDelegateImpl( | 221 delegate_.reset(new AutomaticProfileResetterDelegateImpl(profile_)); |
233 TemplateURLServiceFactory::GetForProfile(profile_))); | |
234 task_runner_for_waiting_ = | 222 task_runner_for_waiting_ = |
235 content::BrowserThread::GetMessageLoopProxyForThread( | 223 content::BrowserThread::GetMessageLoopProxyForThread( |
236 content::BrowserThread::UI); | 224 content::BrowserThread::UI); |
237 | 225 |
238 state_ = STATE_INITIALIZED; | 226 state_ = STATE_INITIALIZED; |
239 } | 227 } |
240 | 228 |
241 void AutomaticProfileResetter::Activate() { | 229 void AutomaticProfileResetter::Activate() { |
242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 230 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
243 DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED); | 231 DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED); |
244 | 232 |
245 if (state_ == STATE_INITIALIZED) { | 233 if (state_ == STATE_INITIALIZED) { |
246 if (!program_.empty()) { | 234 if (!program_.empty()) { |
247 // Some steps in the flow (e.g. loaded modules, file-based memento) are | 235 // Some steps in the flow (e.g. loaded modules, file-based memento) are |
248 // IO-intensive, so defer execution until some time later. | 236 // IO-intensive, so defer execution until some time later. |
249 task_runner_for_waiting_->PostDelayedTask( | 237 task_runner_for_waiting_->PostDelayedTask( |
250 FROM_HERE, | 238 FROM_HERE, |
251 base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow, | 239 base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow, |
252 weak_ptr_factory_.GetWeakPtr()), | 240 weak_ptr_factory_.GetWeakPtr()), |
253 base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds)); | 241 base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds)); |
254 } else { | 242 } else { |
255 // Terminate early if there is no program included (nor set by tests). | 243 // Terminate early if there is no program included (nor set by tests). |
256 state_ = STATE_DISABLED; | 244 state_ = STATE_DISABLED; |
257 } | 245 } |
258 } | 246 } |
259 } | 247 } |
260 | 248 |
249 void AutomaticProfileResetter::TriggerProfileReset(bool send_feedback) { | |
250 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
251 DCHECK(state_ == STATE_AWAITING_USER_CHOICE || state_ == STATE_DONE); | |
252 | |
253 if (state_ == STATE_AWAITING_USER_CHOICE) { | |
254 state_ = STATE_PERFORMING_RESET; | |
255 delegate_->TriggerProfileSettingsReset( | |
256 send_feedback, | |
257 base::Bind(&AutomaticProfileResetter::OnProfileSettingsResetCompleted, | |
258 weak_ptr_factory_.GetWeakPtr())); | |
259 } | |
260 } | |
261 | |
262 void AutomaticProfileResetter::SkipProfileReset() { | |
263 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
264 DCHECK(state_ == STATE_AWAITING_USER_CHOICE || state_ == STATE_DONE); | |
265 | |
266 if (state_ == STATE_AWAITING_USER_CHOICE) { | |
267 delegate_->DismissPrompt(); | |
268 FinishResetPromptFlow(PROMPT_ACTION_NO_RESET); | |
269 } | |
270 } | |
271 | |
272 bool AutomaticProfileResetter::IsResetPromptActive() const { | |
273 return state_ == STATE_AWAITING_USER_CHOICE; | |
274 } | |
275 | |
276 void AutomaticProfileResetter::NotifyDidShowResetBubble() { | |
277 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
278 DCHECK(state_ == STATE_AWAITING_USER_CHOICE || state_ == STATE_DONE); | |
279 | |
280 if (state_ == STATE_AWAITING_USER_CHOICE) { | |
Dan Beam
2013/11/07 00:01:18
nit: no curlies here or on L288-230
engedy
2013/11/08 02:56:40
Ahh, done.
| |
281 has_shown_bubble_ = true; | |
282 } | |
283 } | |
284 | |
285 void AutomaticProfileResetter::NotifyDidOpenWebUIResetDialog() { | |
286 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
287 | |
288 if (state_ == STATE_AWAITING_USER_CHOICE) { | |
289 delegate_->DismissPrompt(); | |
290 } | |
291 } | |
292 | |
293 void AutomaticProfileResetter::NotifyDidCloseWebUIResetDialog( | |
294 bool performed_reset) { | |
295 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
296 | |
297 if (state_ == STATE_AWAITING_USER_CHOICE) { | |
298 FinishResetPromptFlow(has_shown_bubble_ ? | |
299 (performed_reset ? | |
300 PROMPT_FOLLOWED_BY_WEBUI_RESET : | |
301 PROMPT_FOLLOWED_BY_WEBUI_NO_RESET) : | |
302 (performed_reset ? | |
303 PROMPT_SUPPRESSED_BUT_HAD_WEBUI_RESET : | |
304 PROMPT_SUPPRESSED_BUT_HAD_WEBUI_NO_RESET)); | |
305 } | |
306 } | |
307 | |
261 void AutomaticProfileResetter::SetProgramForTesting( | 308 void AutomaticProfileResetter::SetProgramForTesting( |
262 const std::string& program) { | 309 const std::string& program) { |
263 program_ = program; | 310 program_ = program; |
264 } | 311 } |
265 | 312 |
266 void AutomaticProfileResetter::SetHashSeedForTesting( | 313 void AutomaticProfileResetter::SetHashSeedForTesting( |
267 const std::string& hash_key) { | 314 const std::string& hash_key) { |
268 hash_seed_ = hash_key; | 315 hash_seed_ = hash_key; |
269 } | 316 } |
270 | 317 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow, | 363 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow, |
317 weak_ptr_factory_.GetWeakPtr())); | 364 weak_ptr_factory_.GetWeakPtr())); |
318 } | 365 } |
319 } | 366 } |
320 | 367 |
321 void AutomaticProfileResetter::BeginEvaluationFlow() { | 368 void AutomaticProfileResetter::BeginEvaluationFlow() { |
322 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 369 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
323 DCHECK_EQ(state_, STATE_READY); | 370 DCHECK_EQ(state_, STATE_READY); |
324 DCHECK(!program_.empty()); | 371 DCHECK(!program_.empty()); |
325 | 372 |
326 state_ = STATE_WORKING; | 373 state_ = STATE_EVALUATING_CONDITIONS; |
327 memento_in_file_.ReadValue( | 374 memento_in_file_.ReadValue( |
328 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow, | 375 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow, |
329 weak_ptr_factory_.GetWeakPtr())); | 376 weak_ptr_factory_.GetWeakPtr())); |
330 } | 377 } |
331 | 378 |
332 scoped_ptr<base::DictionaryValue> | 379 scoped_ptr<base::DictionaryValue> |
333 AutomaticProfileResetter::BuildEvaluatorProgramInput( | 380 AutomaticProfileResetter::BuildEvaluatorProgramInput( |
334 const std::string& memento_value_in_file) { | 381 const std::string& memento_value_in_file) { |
335 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 382 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
336 | 383 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 scoped_ptr<base::ListValue> loaded_module_digests( | 422 scoped_ptr<base::ListValue> loaded_module_digests( |
376 delegate_->GetLoadedModuleNameDigests()); | 423 delegate_->GetLoadedModuleNameDigests()); |
377 input->Set(kLoadedModuleDigestsKey, loaded_module_digests.release()); | 424 input->Set(kLoadedModuleDigestsKey, loaded_module_digests.release()); |
378 | 425 |
379 return input.Pass(); | 426 return input.Pass(); |
380 } | 427 } |
381 | 428 |
382 void AutomaticProfileResetter::ContinueWithEvaluationFlow( | 429 void AutomaticProfileResetter::ContinueWithEvaluationFlow( |
383 const std::string& memento_value_in_file) { | 430 const std::string& memento_value_in_file) { |
384 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 431 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
385 DCHECK_EQ(state_, STATE_WORKING); | 432 DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); |
386 PrefService* prefs = profile_->GetPrefs(); | 433 PrefService* prefs = profile_->GetPrefs(); |
387 DCHECK(prefs); | 434 DCHECK(prefs); |
388 | 435 |
389 scoped_ptr<base::DictionaryValue> input( | 436 scoped_ptr<base::DictionaryValue> input( |
390 BuildEvaluatorProgramInput(memento_value_in_file)); | 437 BuildEvaluatorProgramInput(memento_value_in_file)); |
391 | 438 |
392 base::SequencedWorkerPool* blocking_pool = | 439 base::SequencedWorkerPool* blocking_pool = |
393 content::BrowserThread::GetBlockingPool(); | 440 content::BrowserThread::GetBlockingPool(); |
394 scoped_refptr<base::TaskRunner> task_runner = | 441 scoped_refptr<base::TaskRunner> task_runner = |
395 blocking_pool->GetTaskRunnerWithShutdownBehavior( | 442 blocking_pool->GetTaskRunnerWithShutdownBehavior( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 } | 483 } |
437 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) { | 484 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) { |
438 bool flag = false; | 485 bool flag = false; |
439 if (interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag) && | 486 if (interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag) && |
440 flag) | 487 flag) |
441 results->satisfied_criteria_mask |= (1 << i); | 488 results->satisfied_criteria_mask |= (1 << i); |
442 } | 489 } |
443 return results.Pass(); | 490 return results.Pass(); |
444 } | 491 } |
445 | 492 |
446 void AutomaticProfileResetter::FinishEvaluationFlow( | |
447 scoped_ptr<EvaluationResults> results) { | |
448 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
449 DCHECK_EQ(state_, STATE_WORKING); | |
450 | |
451 ReportStatistics(results->satisfied_criteria_mask, | |
452 results->combined_status_mask); | |
453 | |
454 if (results->satisfied_criteria_mask != 0 && !results->had_prompted_already) { | |
455 memento_in_prefs_.StoreValue(results->memento_value_in_prefs); | |
456 memento_in_local_state_.StoreValue(results->memento_value_in_local_state); | |
457 memento_in_file_.StoreValue(results->memento_value_in_file); | |
458 | |
459 if (ShouldPerformLiveRun()) { | |
460 delegate_->ShowPrompt(); | |
461 } else { | |
462 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.PromptResult", | |
463 PROMPT_NOT_SHOWN, | |
464 PROMPT_RESULT_MAX); | |
465 } | |
466 } | |
467 | |
468 state_ = STATE_DONE; | |
469 } | |
470 | |
471 void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask, | 493 void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask, |
472 uint32 combined_status_mask) { | 494 uint32 combined_status_mask) { |
473 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask", | 495 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask", |
474 satisfied_criteria_mask, | 496 satisfied_criteria_mask, |
475 kSatisfiedCriteriaMaskMaximumValue); | 497 kSatisfiedCriteriaMaskMaximumValue); |
476 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask", | 498 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask", |
477 combined_status_mask, | 499 combined_status_mask, |
478 kCombinedStatusMaskMaximumValue); | 500 kCombinedStatusMaskMaximumValue); |
479 } | 501 } |
480 | 502 |
503 void AutomaticProfileResetter::FinishEvaluationFlow( | |
504 scoped_ptr<EvaluationResults> results) { | |
505 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
506 DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); | |
507 | |
508 evaluation_results_ = results.Pass(); | |
509 | |
510 ReportStatistics(evaluation_results_->satisfied_criteria_mask, | |
511 evaluation_results_->combined_status_mask); | |
512 | |
513 if (evaluation_results_->satisfied_criteria_mask != 0 && | |
514 !evaluation_results_->had_prompted_already) { | |
515 BeginResetPromptFlow(); | |
516 } else { | |
517 state_ = STATE_DONE; | |
518 } | |
519 } | |
520 | |
521 void AutomaticProfileResetter::BeginResetPromptFlow() { | |
522 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
523 DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); | |
524 | |
525 state_ = STATE_AWAITING_USER_CHOICE; | |
526 | |
527 if (ShouldPerformLiveRun()) { | |
528 delegate_->ShowPrompt(); | |
529 // Start fetching brandcode config in the background speculatively. | |
530 delegate_->FetchBrandcodedDefaultSettingsIfNeeded(); | |
531 } else { | |
532 FinishResetPromptFlow(PROMPT_NOT_SHOWN); | |
533 } | |
534 } | |
535 | |
536 void AutomaticProfileResetter::OnProfileSettingsResetCompleted() { | |
537 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
538 DCHECK_EQ(state_, STATE_PERFORMING_RESET); | |
539 | |
540 delegate_->DismissPrompt(); | |
541 FinishResetPromptFlow(PROMPT_ACTION_RESET); | |
542 } | |
543 | |
544 void AutomaticProfileResetter::ReportPromptResult(PromptResult result) { | |
545 UMA_HISTOGRAM_ENUMERATION( | |
546 "AutomaticProfileReset.PromptResult", result, PROMPT_RESULT_MAX); | |
547 } | |
548 | |
549 void AutomaticProfileResetter::FinishResetPromptFlow(PromptResult result) { | |
550 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
551 DCHECK(state_ == STATE_PERFORMING_RESET || | |
552 state_ == STATE_AWAITING_USER_CHOICE); | |
553 | |
554 memento_in_prefs_.StoreValue(evaluation_results_->memento_value_in_prefs); | |
555 memento_in_local_state_.StoreValue( | |
556 evaluation_results_->memento_value_in_local_state); | |
557 memento_in_file_.StoreValue(evaluation_results_->memento_value_in_file); | |
558 | |
559 ReportPromptResult(result); | |
560 | |
561 state_ = STATE_DONE; | |
562 } | |
563 | |
481 void AutomaticProfileResetter::Shutdown() { | 564 void AutomaticProfileResetter::Shutdown() { |
482 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 565 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
483 | 566 |
567 // Conclude the flow in case the bubble was shown, so as to prevent showing | |
568 // the prompt on next start-up. | |
569 if (state_ == STATE_AWAITING_USER_CHOICE && has_shown_bubble_) | |
570 FinishResetPromptFlow(PROMPT_IGNORED); | |
571 | |
484 state_ = STATE_DISABLED; | 572 state_ = STATE_DISABLED; |
485 delegate_.reset(); | 573 delegate_.reset(); |
486 weak_ptr_factory_.InvalidateWeakPtrs(); | 574 weak_ptr_factory_.InvalidateWeakPtrs(); |
487 } | 575 } |
OLD | NEW |