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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 const uint32 kCombinedStatusMaskMaximumValue = | 102 const uint32 kCombinedStatusMaskMaximumValue = |
103 (1u << kCombinedStatusMaskNumberOfBits); | 103 (1u << kCombinedStatusMaskNumberOfBits); |
104 | 104 |
105 COMPILE_ASSERT( | 105 COMPILE_ASSERT( |
106 arraysize(kSatisfiedCriteriaMaskKeys) == kSatisfiedCriteriaMaskNumberOfBits, | 106 arraysize(kSatisfiedCriteriaMaskKeys) == kSatisfiedCriteriaMaskNumberOfBits, |
107 satisfied_criteria_mask_bits_mismatch); | 107 satisfied_criteria_mask_bits_mismatch); |
108 COMPILE_ASSERT( | 108 COMPILE_ASSERT( |
109 arraysize(kCombinedStatusMaskKeys) == kCombinedStatusMaskNumberOfBits, | 109 arraysize(kCombinedStatusMaskKeys) == kCombinedStatusMaskNumberOfBits, |
110 combined_status_mask_bits_mismatch); | 110 combined_status_mask_bits_mismatch); |
111 | 111 |
112 // Enumeration of the possible outcomes of showing the profile reset prompt. | |
113 enum PromptResult { | |
114 // Prompt was not shown because only a dry-run was performed. | |
115 PROMPT_NOT_SHOWN, | |
116 PROMPT_ACTION_RESET, | |
117 PROMPT_ACTION_NO_RESET, | |
118 PROMPT_DISMISSED, | |
119 // Prompt was still shown (not dismissed by the user) when Chrome was closed. | |
120 PROMPT_IGNORED, | |
121 PROMPT_RESULT_MAX | |
122 }; | |
123 | |
124 // Returns whether or not a dry-run shall be performed. | 112 // Returns whether or not a dry-run shall be performed. |
125 bool ShouldPerformDryRun() { | 113 bool ShouldPerformDryRun() { |
126 return StartsWithASCII( | 114 return StartsWithASCII( |
127 base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName), | 115 base::FieldTrialList::FindFullName(kAutomaticProfileResetStudyName), |
128 kAutomaticProfileResetStudyDryRunGroupName, true); | 116 kAutomaticProfileResetStudyDryRunGroupName, true); |
129 } | 117 } |
130 | 118 |
131 // Returns whether or not a live-run shall be performed. | 119 // Returns whether or not a live-run shall be performed. |
132 bool ShouldPerformLiveRun() { | 120 bool ShouldPerformLiveRun() { |
133 return StartsWithASCII( | 121 return StartsWithASCII( |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 } // namespace | 181 } // namespace |
194 | 182 |
195 | 183 |
196 // AutomaticProfileResetter -------------------------------------------------- | 184 // AutomaticProfileResetter -------------------------------------------------- |
197 | 185 |
198 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile) | 186 AutomaticProfileResetter::AutomaticProfileResetter(Profile* profile) |
199 : profile_(profile), | 187 : profile_(profile), |
200 state_(STATE_UNINITIALIZED), | 188 state_(STATE_UNINITIALIZED), |
201 enumeration_of_loaded_modules_ready_(false), | 189 enumeration_of_loaded_modules_ready_(false), |
202 template_url_service_ready_(false), | 190 template_url_service_ready_(false), |
191 has_shown_bubble_(false), | |
203 memento_in_prefs_(profile_), | 192 memento_in_prefs_(profile_), |
204 memento_in_local_state_(profile_), | 193 memento_in_local_state_(profile_), |
205 memento_in_file_(profile_), | 194 memento_in_file_(profile_), |
206 weak_ptr_factory_(this) { | 195 weak_ptr_factory_(this) { |
207 DCHECK(profile_); | 196 DCHECK(profile_); |
208 } | 197 } |
209 | 198 |
210 AutomaticProfileResetter::~AutomaticProfileResetter() {} | 199 AutomaticProfileResetter::~AutomaticProfileResetter() {} |
211 | 200 |
212 void AutomaticProfileResetter::Initialize() { | 201 void AutomaticProfileResetter::Initialize() { |
(...skipping 14 matching lines...) Expand all Loading... | |
227 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED).as_string(); | 216 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED).as_string(); |
228 } else { // ShouldPerformDryRun() | 217 } else { // ShouldPerformDryRun() |
229 program_ = resources.GetRawDataResource( | 218 program_ = resources.GetRawDataResource( |
230 IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY).as_string(); | 219 IDR_AUTOMATIC_PROFILE_RESET_RULES_DRY).as_string(); |
231 hash_seed_ = resources.GetRawDataResource( | 220 hash_seed_ = resources.GetRawDataResource( |
232 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY).as_string(); | 221 IDR_AUTOMATIC_PROFILE_RESET_HASH_SEED_DRY).as_string(); |
233 } | 222 } |
234 } | 223 } |
235 | 224 |
236 delegate_.reset(new AutomaticProfileResetterDelegateImpl( | 225 delegate_.reset(new AutomaticProfileResetterDelegateImpl( |
237 TemplateURLServiceFactory::GetForProfile(profile_))); | 226 profile_, ProfileResetter::ALL)); |
238 task_runner_for_waiting_ = | 227 task_runner_for_waiting_ = |
239 content::BrowserThread::GetMessageLoopProxyForThread( | 228 content::BrowserThread::GetMessageLoopProxyForThread( |
240 content::BrowserThread::UI); | 229 content::BrowserThread::UI); |
241 | 230 |
242 state_ = STATE_INITIALIZED; | 231 state_ = STATE_INITIALIZED; |
243 } | 232 } |
244 | 233 |
245 void AutomaticProfileResetter::Activate() { | 234 void AutomaticProfileResetter::Activate() { |
246 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 235 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
247 DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED); | 236 DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED); |
248 | 237 |
249 if (state_ == STATE_INITIALIZED) { | 238 if (state_ == STATE_INITIALIZED) { |
250 if (!program_.empty()) { | 239 if (!program_.empty()) { |
251 // Some steps in the flow (e.g. loaded modules, file-based memento) are | 240 // Some steps in the flow (e.g. loaded modules, file-based memento) are |
252 // IO-intensive, so defer execution until some time later. | 241 // IO-intensive, so defer execution until some time later. |
253 task_runner_for_waiting_->PostDelayedTask( | 242 task_runner_for_waiting_->PostDelayedTask( |
254 FROM_HERE, | 243 FROM_HERE, |
255 base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow, | 244 base::Bind(&AutomaticProfileResetter::PrepareEvaluationFlow, |
256 weak_ptr_factory_.GetWeakPtr()), | 245 weak_ptr_factory_.GetWeakPtr()), |
257 base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds)); | 246 base::TimeDelta::FromSeconds(kEvaluationFlowDelayInSeconds)); |
258 } else { | 247 } else { |
259 // Terminate early if there is no program included (nor set by tests). | 248 // Terminate early if there is no program included (nor set by tests). |
260 state_ = STATE_DISABLED; | 249 state_ = STATE_DISABLED; |
261 } | 250 } |
262 } | 251 } |
263 } | 252 } |
264 | 253 |
254 void AutomaticProfileResetter::TriggerProfileReset(bool send_feedback) { | |
255 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
256 DCHECK_EQ(state_, STATE_AWAITING_USER_CHOICE); | |
257 | |
258 state_ = STATE_PERFORMING_RESET; | |
259 delegate_->TriggerProfileSettingsReset( | |
260 send_feedback, | |
261 base::Bind(&AutomaticProfileResetter::OnProfileSettingsResetCompleted, | |
262 weak_ptr_factory_.GetWeakPtr())); | |
263 } | |
264 | |
265 void AutomaticProfileResetter::SkipProfileReset() { | |
266 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
267 DCHECK_EQ(state_, STATE_AWAITING_USER_CHOICE); | |
268 | |
269 FinishResetPromptFlow(PROMPT_ACTION_NO_RESET); | |
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_EQ(state_, STATE_AWAITING_USER_CHOICE); | |
279 | |
280 has_shown_bubble_ = true; | |
281 } | |
282 | |
283 void AutomaticProfileResetter::NotifyDidOpenWebUIResetDialog() { | |
284 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
285 | |
286 // This notification is invoked unconditionally by the WebUI, but we only care | |
287 // about it when the prompt is currently active. | |
288 if (state_ == STATE_AWAITING_USER_CHOICE) | |
289 delegate_->DismissPrompt(); | |
290 } | |
291 | |
292 void AutomaticProfileResetter::NotifyDidCloseWebUIResetDialog( | |
293 bool performed_reset) { | |
294 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
295 | |
296 // This notification is invoked unconditionally by the WebUI, but we only care | |
297 // about it when the prompt is currently active. | |
MAD
2013/11/11 16:38:32
indent -2
engedy
2013/11/13 00:40:44
Done.
| |
298 if (state_ == STATE_AWAITING_USER_CHOICE) { | |
299 FinishResetPromptFlow(has_shown_bubble_ ? | |
300 (performed_reset ? | |
301 PROMPT_FOLLOWED_BY_WEBUI_RESET : | |
302 PROMPT_FOLLOWED_BY_WEBUI_NO_RESET) : | |
303 (performed_reset ? | |
304 PROMPT_SUPPRESSED_BUT_HAD_WEBUI_RESET : | |
305 PROMPT_SUPPRESSED_BUT_HAD_WEBUI_NO_RESET)); | |
306 } | |
307 } | |
308 | |
309 void AutomaticProfileResetter::Shutdown() { | |
310 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
311 | |
312 // At this point, metrics service is already shut down and the local state | |
313 // should already no longer be written... | |
314 | |
315 // Conclude the flow in case the bubble was shown, so as to prevent showing | |
316 // the prompt on next start-up. However, if the bubble was not even shown, or | |
317 // if the ongoing reset did not complete, show the prompt on next start-up. | |
318 if (state_ == STATE_AWAITING_USER_CHOICE && has_shown_bubble_) | |
319 FinishResetPromptFlow(PROMPT_IGNORED); | |
320 else if (state_ == STATE_AWAITING_USER_CHOICE || | |
321 state_ == STATE_PERFORMING_RESET) | |
322 delegate_->DismissPrompt(); | |
323 | |
324 state_ = STATE_DISABLED; | |
325 delegate_.reset(); | |
326 weak_ptr_factory_.InvalidateWeakPtrs(); | |
327 } | |
328 | |
265 void AutomaticProfileResetter::SetProgramForTesting( | 329 void AutomaticProfileResetter::SetProgramForTesting( |
266 const std::string& program) { | 330 const std::string& program) { |
267 program_ = program; | 331 program_ = program; |
268 } | 332 } |
269 | 333 |
270 void AutomaticProfileResetter::SetHashSeedForTesting( | 334 void AutomaticProfileResetter::SetHashSeedForTesting( |
271 const std::string& hash_key) { | 335 const std::string& hash_key) { |
272 hash_seed_ = hash_key; | 336 hash_seed_ = hash_key; |
273 } | 337 } |
274 | 338 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow, | 384 base::Bind(&AutomaticProfileResetter::BeginEvaluationFlow, |
321 weak_ptr_factory_.GetWeakPtr())); | 385 weak_ptr_factory_.GetWeakPtr())); |
322 } | 386 } |
323 } | 387 } |
324 | 388 |
325 void AutomaticProfileResetter::BeginEvaluationFlow() { | 389 void AutomaticProfileResetter::BeginEvaluationFlow() { |
326 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 390 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
327 DCHECK_EQ(state_, STATE_READY); | 391 DCHECK_EQ(state_, STATE_READY); |
328 DCHECK(!program_.empty()); | 392 DCHECK(!program_.empty()); |
329 | 393 |
330 state_ = STATE_WORKING; | 394 state_ = STATE_EVALUATING_CONDITIONS; |
331 memento_in_file_.ReadValue( | 395 memento_in_file_.ReadValue( |
332 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow, | 396 base::Bind(&AutomaticProfileResetter::ContinueWithEvaluationFlow, |
333 weak_ptr_factory_.GetWeakPtr())); | 397 weak_ptr_factory_.GetWeakPtr())); |
334 } | 398 } |
335 | 399 |
336 scoped_ptr<base::DictionaryValue> | 400 scoped_ptr<base::DictionaryValue> |
337 AutomaticProfileResetter::BuildEvaluatorProgramInput( | 401 AutomaticProfileResetter::BuildEvaluatorProgramInput( |
338 const std::string& memento_value_in_file) { | 402 const std::string& memento_value_in_file) { |
339 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 403 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
340 | 404 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
379 scoped_ptr<base::ListValue> loaded_module_digests( | 443 scoped_ptr<base::ListValue> loaded_module_digests( |
380 delegate_->GetLoadedModuleNameDigests()); | 444 delegate_->GetLoadedModuleNameDigests()); |
381 input->Set(kLoadedModuleDigestsKey, loaded_module_digests.release()); | 445 input->Set(kLoadedModuleDigestsKey, loaded_module_digests.release()); |
382 | 446 |
383 return input.Pass(); | 447 return input.Pass(); |
384 } | 448 } |
385 | 449 |
386 void AutomaticProfileResetter::ContinueWithEvaluationFlow( | 450 void AutomaticProfileResetter::ContinueWithEvaluationFlow( |
387 const std::string& memento_value_in_file) { | 451 const std::string& memento_value_in_file) { |
388 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 452 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
389 DCHECK_EQ(state_, STATE_WORKING); | 453 DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); |
390 PrefService* prefs = profile_->GetPrefs(); | 454 PrefService* prefs = profile_->GetPrefs(); |
391 DCHECK(prefs); | 455 DCHECK(prefs); |
392 | 456 |
393 scoped_ptr<base::DictionaryValue> input( | 457 scoped_ptr<base::DictionaryValue> input( |
394 BuildEvaluatorProgramInput(memento_value_in_file)); | 458 BuildEvaluatorProgramInput(memento_value_in_file)); |
395 | 459 |
396 base::SequencedWorkerPool* blocking_pool = | 460 base::SequencedWorkerPool* blocking_pool = |
397 content::BrowserThread::GetBlockingPool(); | 461 content::BrowserThread::GetBlockingPool(); |
398 scoped_refptr<base::TaskRunner> task_runner = | 462 scoped_refptr<base::TaskRunner> task_runner = |
399 blocking_pool->GetTaskRunnerWithShutdownBehavior( | 463 blocking_pool->GetTaskRunnerWithShutdownBehavior( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 } | 504 } |
441 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) { | 505 for (size_t i = 0; i < arraysize(kSatisfiedCriteriaMaskKeys); ++i) { |
442 bool flag = false; | 506 bool flag = false; |
443 if (interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag) && | 507 if (interpreter.GetOutputBoolean(kSatisfiedCriteriaMaskKeys[i], &flag) && |
444 flag) | 508 flag) |
445 results->satisfied_criteria_mask |= (1 << i); | 509 results->satisfied_criteria_mask |= (1 << i); |
446 } | 510 } |
447 return results.Pass(); | 511 return results.Pass(); |
448 } | 512 } |
449 | 513 |
450 void AutomaticProfileResetter::FinishEvaluationFlow( | |
451 scoped_ptr<EvaluationResults> results) { | |
452 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
453 DCHECK_EQ(state_, STATE_WORKING); | |
454 | |
455 ReportStatistics(results->satisfied_criteria_mask, | |
456 results->combined_status_mask); | |
457 | |
458 if (results->satisfied_criteria_mask != 0 && !results->had_prompted_already) { | |
459 memento_in_prefs_.StoreValue(results->memento_value_in_prefs); | |
460 memento_in_local_state_.StoreValue(results->memento_value_in_local_state); | |
461 memento_in_file_.StoreValue(results->memento_value_in_file); | |
462 | |
463 if (ShouldPerformLiveRun()) { | |
464 delegate_->ShowPrompt(); | |
465 } else { | |
466 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.PromptResult", | |
467 PROMPT_NOT_SHOWN, | |
468 PROMPT_RESULT_MAX); | |
469 } | |
470 } | |
471 | |
472 state_ = STATE_DONE; | |
473 } | |
474 | |
475 void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask, | 514 void AutomaticProfileResetter::ReportStatistics(uint32 satisfied_criteria_mask, |
476 uint32 combined_status_mask) { | 515 uint32 combined_status_mask) { |
477 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask", | 516 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.SatisfiedCriteriaMask", |
478 satisfied_criteria_mask, | 517 satisfied_criteria_mask, |
479 kSatisfiedCriteriaMaskMaximumValue); | 518 kSatisfiedCriteriaMaskMaximumValue); |
480 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask", | 519 UMA_HISTOGRAM_ENUMERATION("AutomaticProfileReset.CombinedStatusMask", |
481 combined_status_mask, | 520 combined_status_mask, |
482 kCombinedStatusMaskMaximumValue); | 521 kCombinedStatusMaskMaximumValue); |
483 } | 522 } |
484 | 523 |
485 void AutomaticProfileResetter::Shutdown() { | 524 void AutomaticProfileResetter::FinishEvaluationFlow( |
525 scoped_ptr<EvaluationResults> results) { | |
486 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 526 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
527 DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); | |
487 | 528 |
488 state_ = STATE_DISABLED; | 529 evaluation_results_ = results.Pass(); |
489 delegate_.reset(); | 530 |
490 weak_ptr_factory_.InvalidateWeakPtrs(); | 531 ReportStatistics(evaluation_results_->satisfied_criteria_mask, |
532 evaluation_results_->combined_status_mask); | |
533 | |
534 if (evaluation_results_->satisfied_criteria_mask != 0 && | |
535 !evaluation_results_->had_prompted_already) { | |
536 BeginResetPromptFlow(); | |
537 } else { | |
538 state_ = STATE_DONE; | |
539 } | |
491 } | 540 } |
541 | |
542 void AutomaticProfileResetter::BeginResetPromptFlow() { | |
543 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
544 DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); | |
545 | |
546 state_ = STATE_AWAITING_USER_CHOICE; | |
547 | |
548 if (ShouldPerformLiveRun() && delegate_->ShowPrompt()) { | |
549 // Start fetching brandcode config in the background speculatively. | |
550 delegate_->FetchBrandcodedDefaultSettingsIfNeeded(); | |
551 } else { | |
552 FinishResetPromptFlow(PROMPT_NOT_SHOWN); | |
553 } | |
554 } | |
555 | |
556 void AutomaticProfileResetter::OnProfileSettingsResetCompleted() { | |
557 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
558 DCHECK_EQ(state_, STATE_PERFORMING_RESET); | |
559 | |
560 FinishResetPromptFlow(PROMPT_ACTION_RESET); | |
561 } | |
562 | |
563 void AutomaticProfileResetter::ReportPromptResult(PromptResult result) { | |
564 UMA_HISTOGRAM_ENUMERATION( | |
565 "AutomaticProfileReset.PromptResult", result, PROMPT_RESULT_MAX); | |
566 } | |
567 | |
568 void AutomaticProfileResetter::FinishResetPromptFlow(PromptResult result) { | |
569 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
570 DCHECK(state_ == STATE_PERFORMING_RESET || | |
571 state_ == STATE_AWAITING_USER_CHOICE); | |
572 | |
573 delegate_->DismissPrompt(); | |
574 | |
575 memento_in_prefs_.StoreValue(evaluation_results_->memento_value_in_prefs); | |
576 memento_in_local_state_.StoreValue( | |
577 evaluation_results_->memento_value_in_local_state); | |
578 memento_in_file_.StoreValue(evaluation_results_->memento_value_in_file); | |
579 | |
580 ReportPromptResult(result); | |
581 | |
582 state_ = STATE_DONE; | |
583 } | |
OLD | NEW |