OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/safe_browsing/srt_fetcher_win.h" | 5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
112 | 112 |
113 const char kFoundUwsMetricName[] = "SoftwareReporter.FoundUwS"; | 113 const char kFoundUwsMetricName[] = "SoftwareReporter.FoundUwS"; |
114 const char kFoundUwsReadErrorMetricName[] = | 114 const char kFoundUwsReadErrorMetricName[] = |
115 "SoftwareReporter.FoundUwSReadError"; | 115 "SoftwareReporter.FoundUwSReadError"; |
116 const char kScanTimesMetricName[] = "SoftwareReporter.UwSScanTimes"; | 116 const char kScanTimesMetricName[] = "SoftwareReporter.UwSScanTimes"; |
117 const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed"; | 117 const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed"; |
118 | 118 |
119 // Reports metrics about the software reporter via UMA (and sometimes Rappor). | 119 // Reports metrics about the software reporter via UMA (and sometimes Rappor). |
120 class UMAHistogramReporter { | 120 class UMAHistogramReporter { |
121 public: | 121 public: |
122 explicit UMAHistogramReporter(const std::string& suffix = std::string()) | 122 UMAHistogramReporter() : UMAHistogramReporter(std::string()) {} |
123 | |
124 explicit UMAHistogramReporter(const std::string& suffix) | |
123 : suffix_(suffix), | 125 : suffix_(suffix), |
124 registry_key_(suffix.empty() ? kSoftwareRemovalToolRegistryKey | 126 registry_key_(suffix.empty() ? kSoftwareRemovalToolRegistryKey |
125 : base::StringPrintf( | 127 : base::StringPrintf( |
126 L"%ls\\%ls", | 128 L"%ls\\%ls", |
127 kSoftwareRemovalToolRegistryKey, | 129 kSoftwareRemovalToolRegistryKey, |
128 base::UTF8ToUTF16(suffix).c_str())) { | 130 base::UTF8ToUTF16(suffix).c_str())) { |
129 } | 131 } |
130 | 132 |
131 // Reports the software reporter tool's version via UMA. | 133 // Reports the software reporter tool's version via UMA. |
132 void ReportVersion(const base::Version& version) const { | 134 void ReportVersion(const base::Version& version) const { |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 prefs->SetString(prefs::kSwReporterPromptVersion, | 577 prefs->SetString(prefs::kSwReporterPromptVersion, |
576 reporter_version.GetString()); | 578 reporter_version.GetString()); |
577 | 579 |
578 // Download the SRT. | 580 // Download the SRT. |
579 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START); | 581 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START); |
580 | 582 |
581 // All the work happens in the self-deleting class below. | 583 // All the work happens in the self-deleting class below. |
582 new SRTFetcher(profile); | 584 new SRTFetcher(profile); |
583 } | 585 } |
584 | 586 |
585 // This class tries to run the reporter and reacts to its exit code. It | 587 // This class tries to run a queue of reporters and react to their exit codes. |
586 // schedules subsequent runs as needed, or retries as soon as a browser is | 588 // It schedules subsequent runs of the queue as needed, or retries as soon as a |
587 // available when none is on first try. | 589 // browser is available when none is on first try. |
588 class ReporterRunner : public chrome::BrowserListObserver { | 590 class ReporterRunner : public chrome::BrowserListObserver { |
589 public: | 591 public: |
590 // Starts the sequence of attempts to run the reporter. | 592 // Registers |invocations| to run next time |TryToRun| is scheduled. (And if |
591 static void Run(const SwReporterInvocation& invocation, | 593 // it's not already scheduled, call it now.) |
592 const base::Version& version, | 594 static void ScheduleInvocations( |
593 scoped_refptr<base::TaskRunner> main_thread_task_runner, | 595 const SwReporterQueue& invocations, |
594 scoped_refptr<base::TaskRunner> blocking_task_runner) { | 596 const base::Version& version, |
597 scoped_refptr<base::TaskRunner> main_thread_task_runner, | |
598 scoped_refptr<base::TaskRunner> blocking_task_runner) { | |
595 if (!instance_) | 599 if (!instance_) |
596 instance_ = new ReporterRunner; | 600 instance_ = new ReporterRunner; |
grt (UTC plus 2)
2016/09/13 06:32:25
since this is intentionally leaked, please use ANN
Joe Mason
2016/09/13 19:24:54
Done.
| |
597 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 601 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
598 // There's nothing to do if the path and version of the reporter has not | 602 |
599 // changed, we just keep running the tasks that are running now. | 603 // There's nothing to do if the invocation parameters and version of the |
600 if (instance_->invocation_ == invocation && instance_->version_.IsValid() && | 604 // reporter have not changed, we just keep running the tasks that are |
601 instance_->version_ == version) | 605 // running now. |
606 if (instance_->pending_invocations_ == invocations && | |
607 instance_->version_.IsValid() && instance_->version_ == version) | |
602 return; | 608 return; |
603 | 609 |
604 instance_->invocation_ = invocation; | 610 instance_->pending_invocations_ = invocations; |
605 instance_->version_ = version; | 611 instance_->version_ = version; |
606 instance_->main_thread_task_runner_ = std::move(main_thread_task_runner); | 612 instance_->main_thread_task_runner_ = std::move(main_thread_task_runner); |
607 instance_->blocking_task_runner_ = std::move(blocking_task_runner); | 613 instance_->blocking_task_runner_ = std::move(blocking_task_runner); |
608 | 614 |
609 if (instance_->first_run_) { | 615 if (instance_->first_run_) { |
610 instance_->first_run_ = false; | 616 instance_->first_run_ = false; |
611 instance_->TryToRun(); | 617 instance_->TryToRun(); |
612 } | 618 } |
613 } | 619 } |
614 | 620 |
615 private: | 621 private: |
616 ReporterRunner() {} | 622 ReporterRunner() {} |
617 ~ReporterRunner() override {} | 623 ~ReporterRunner() override {} |
618 | 624 |
619 // BrowserListObserver. | 625 // BrowserListObserver. |
620 void OnBrowserSetLastActive(Browser* browser) override {} | 626 void OnBrowserSetLastActive(Browser* browser) override {} |
621 void OnBrowserRemoved(Browser* browser) override {} | 627 void OnBrowserRemoved(Browser* browser) override {} |
622 void OnBrowserAdded(Browser* browser) override { | 628 void OnBrowserAdded(Browser* browser) override { |
623 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 629 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
624 DCHECK(browser); | 630 DCHECK(browser); |
625 MaybeFetchSRT(browser, version_); | 631 MaybeFetchSRT(browser, version_); |
626 BrowserList::RemoveObserver(this); | 632 BrowserList::RemoveObserver(this); |
627 } | 633 } |
628 | 634 |
629 // This method is called on the UI thread when the reporter run has completed. | 635 // Launches the command line at the head of the queue. |
630 // This is run as a task posted from an interruptible worker thread so should | 636 void ScheduleNextInvocation() { |
631 // be resilient to unexpected shutdown. | 637 DCHECK(!current_invocations_.empty()); |
638 auto next_invocation = current_invocations_.front(); | |
639 current_invocations_.pop(); | |
640 | |
641 if (g_testing_delegate_) | |
642 g_testing_delegate_->NotifyLaunchReady(); | |
643 | |
644 // It's OK to simply |PostTaskAndReplyWithResult| so that | |
645 // |LaunchAndWaitForExit| doesn't need to access |main_thread_task_runner_| | |
646 // since the callback is not delayed and the test task runner won't need to | |
647 // force it. | |
648 base::PostTaskAndReplyWithResult( | |
649 blocking_task_runner_.get(), FROM_HERE, | |
650 base::Bind(&LaunchAndWaitForExit, next_invocation), | |
651 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), | |
652 base::Time::Now(), version_, next_invocation)); | |
653 } | |
654 | |
655 // This method is called on the UI thread when an invocation of the reporter | |
656 // has completed. This is run as a task posted from an interruptible worker | |
657 // thread so should be resilient to unexpected shutdown. | |
632 void ReporterDone(const base::Time& reporter_start_time, | 658 void ReporterDone(const base::Time& reporter_start_time, |
633 const base::Version& version, | 659 const base::Version& version, |
634 const SwReporterInvocation& finished_invocation, | 660 const SwReporterInvocation& finished_invocation, |
635 int exit_code) { | 661 int exit_code) { |
636 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 662 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
637 | 663 |
638 if (g_testing_delegate_) | 664 if (g_testing_delegate_) |
639 g_testing_delegate_->NotifyReporterDone(); | 665 g_testing_delegate_->NotifyReporterDone(); |
640 | 666 |
641 base::TimeDelta reporter_running_time = | 667 base::TimeDelta reporter_running_time = |
642 base::Time::Now() - reporter_start_time; | 668 base::Time::Now() - reporter_start_time; |
643 // Don't continue when the reporter process failed to launch, but still try | 669 |
644 // again after the regular delay. It's not worth retrying earlier, risking | 670 // Don't continue the current queue of reporters if one failed to launch. |
645 // running too often if it always fails, since not many users fail here. | 671 if (exit_code == kReporterFailureExitCode) |
646 main_thread_task_runner_->PostDelayedTask( | 672 current_invocations_ = SwReporterQueue(); |
647 FROM_HERE, | 673 |
648 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), | 674 // As soon as we're not running this queue, schedule the next overall queue |
649 base::TimeDelta::FromDays(days_between_reporter_runs_)); | 675 // run after the regular delay. (If there was a failure it's not worth |
676 // retrying earlier, risking running too often if it always fails, since | |
677 // not many users fail here.) | |
678 if (current_invocations_.empty()) { | |
679 main_thread_task_runner_->PostDelayedTask( | |
680 FROM_HERE, | |
681 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), | |
682 base::TimeDelta::FromDays(days_between_reporter_runs_)); | |
683 } else { | |
684 ScheduleNextInvocation(); | |
685 } | |
686 | |
687 // If the reporter failed to launch, do not process the results. (The exit | |
688 // code itself doesn't need to be logged in this case because | |
689 // SW_REPORTER_FAILED_TO_START is logged in |LaunchAndWaitForExit|.) | |
650 if (exit_code == kReporterFailureExitCode) | 690 if (exit_code == kReporterFailureExitCode) |
651 return; | 691 return; |
652 | 692 |
653 UMAHistogramReporter uma(finished_invocation.suffix); | 693 UMAHistogramReporter uma(finished_invocation.suffix); |
654 uma.ReportVersion(version); | 694 uma.ReportVersion(version); |
655 uma.ReportExitCode(exit_code); | 695 uma.ReportExitCode(exit_code); |
656 uma.ReportFoundUwS(!finished_invocation.is_experimental /*use_rappor*/); | 696 uma.ReportFoundUwS(finished_invocation.flags & |
697 SwReporterInvocation::FLAG_LOG_TO_RAPPOR); | |
657 | 698 |
658 // Only save results from the canonical version of the software. | |
659 PrefService* local_state = g_browser_process->local_state(); | 699 PrefService* local_state = g_browser_process->local_state(); |
660 if (local_state && !finished_invocation.is_experimental) { | 700 if (local_state) { |
661 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code); | 701 if (finished_invocation.flags & SwReporterInvocation::FLAG_LOG_TO_PREFS) |
csharp
2016/09/13 17:09:03
LOGS_TO_PREFS -> LOG_REPORTER_LAST_EXIT_CODE? Sinc
Joe Mason
2016/09/13 19:24:55
Done.
| |
702 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code); | |
662 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered, | 703 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered, |
663 base::Time::Now().ToInternalValue()); | 704 base::Time::Now().ToInternalValue()); |
664 } | 705 } |
665 uma.ReportRuntime(reporter_running_time); | 706 uma.ReportRuntime(reporter_running_time); |
666 uma.ReportScanTimes(); | 707 uma.ReportScanTimes(); |
667 uma.ReportMemoryUsage(); | 708 uma.ReportMemoryUsage(); |
668 | 709 |
669 // Only continue to launch the prompt for the canonical version. | 710 if (!(finished_invocation.flags & |
670 if (finished_invocation.is_experimental) | 711 SwReporterInvocation::FLAG_TRIGGER_PROMPT)) |
671 return; | 712 return; |
672 | 713 |
673 if (!IsInSRTPromptFieldTrialGroups()) { | 714 if (!IsInSRTPromptFieldTrialGroups()) { |
674 // Knowing about disabled field trial is more important than reporter not | 715 // Knowing about disabled field trial is more important than reporter not |
675 // finding anything to remove, so check this case first. | 716 // finding anything to remove, so check this case first. |
676 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL); | 717 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL); |
677 return; | 718 return; |
678 } | 719 } |
679 | 720 |
680 if (exit_code != kSwReporterPostRebootCleanupNeeded && | 721 if (exit_code != kSwReporterPostRebootCleanupNeeded && |
(...skipping 14 matching lines...) Expand all Loading... | |
695 BrowserList::AddObserver(this); | 736 BrowserList::AddObserver(this); |
696 } else { | 737 } else { |
697 MaybeFetchSRT(browser, version_); | 738 MaybeFetchSRT(browser, version_); |
698 } | 739 } |
699 } | 740 } |
700 | 741 |
701 void TryToRun() { | 742 void TryToRun() { |
702 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 743 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
703 PrefService* local_state = g_browser_process->local_state(); | 744 PrefService* local_state = g_browser_process->local_state(); |
704 if (!version_.IsValid() || !local_state) { | 745 if (!version_.IsValid() || !local_state) { |
705 DCHECK(first_run_); | 746 DCHECK(first_run_); |
grt (UTC plus 2)
2016/09/13 06:32:25
this is guaranteed to DCHECK if the condition abov
Joe Mason
2016/09/13 19:24:54
I think that's the intent, but I'm not sure how th
grt (UTC plus 2)
2016/09/13 19:47:22
Ack, though the code here doesn't make sense. Plea
Joe Mason
2016/09/13 21:34:42
Done.
| |
706 return; | 747 return; |
707 } | 748 } |
708 | 749 |
709 // Run the reporter if it hasn't been triggered in the last | 750 // Run a queue of reporters if none have been triggered in the last |
710 // |days_between_reporter_runs_| days, which depends if there is a pending | 751 // |days_between_reporter_runs_| days, which depends if there is a pending |
711 // prompt to be added to Chrome's menu. | 752 // prompt to be added to Chrome's menu. |
712 if (local_state->GetBoolean(prefs::kSwReporterPendingPrompt)) { | 753 if (local_state->GetBoolean(prefs::kSwReporterPendingPrompt)) { |
713 days_between_reporter_runs_ = kDaysBetweenSwReporterRunsForPendingPrompt; | 754 days_between_reporter_runs_ = kDaysBetweenSwReporterRunsForPendingPrompt; |
714 RecordReporterStepHistogram(SW_REPORTER_RAN_DAILY); | 755 RecordReporterStepHistogram(SW_REPORTER_RAN_DAILY); |
715 } else { | 756 } else { |
716 days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; | 757 days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; |
717 } | 758 } |
759 const base::Time now = base::Time::Now(); | |
718 const base::Time last_time_triggered = base::Time::FromInternalValue( | 760 const base::Time last_time_triggered = base::Time::FromInternalValue( |
719 local_state->GetInt64(prefs::kSwReporterLastTimeTriggered)); | 761 local_state->GetInt64(prefs::kSwReporterLastTimeTriggered)); |
720 base::TimeDelta next_trigger_delay( | 762 const base::Time next_trigger( |
721 last_time_triggered + | 763 last_time_triggered + |
722 base::TimeDelta::FromDays(days_between_reporter_runs_) - | 764 base::TimeDelta::FromDays(days_between_reporter_runs_)); |
723 base::Time::Now()); | 765 if (!pending_invocations_.empty() && |
724 if (next_trigger_delay.ToInternalValue() <= 0 || | 766 (next_trigger <= now || |
725 // Also make sure the kSwReporterLastTimeTriggered value is not set in | 767 // Also make sure the kSwReporterLastTimeTriggered value is not set in |
726 // the future. | 768 // the future. |
727 last_time_triggered > base::Time::Now()) { | 769 last_time_triggered > now)) { |
728 if (g_testing_delegate_) | 770 DCHECK(current_invocations_.empty()); |
729 g_testing_delegate_->NotifyLaunchReady(); | 771 current_invocations_ = pending_invocations_; |
730 | 772 ScheduleNextInvocation(); |
731 // It's OK to simply |PostTaskAndReplyWithResult| so that | |
732 // |LaunchAndWaitForExit| doesn't need to access | |
733 // |main_thread_task_runner_| since the callback is not delayed and the | |
734 // test task runner won't need to force it. | |
735 base::PostTaskAndReplyWithResult( | |
736 blocking_task_runner_.get(), FROM_HERE, | |
737 base::Bind(&LaunchAndWaitForExit, invocation_), | |
738 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), | |
739 base::Time::Now(), version_, invocation_)); | |
740 } else { | 773 } else { |
741 main_thread_task_runner_->PostDelayedTask( | 774 main_thread_task_runner_->PostDelayedTask( |
742 FROM_HERE, | 775 FROM_HERE, |
743 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), | 776 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), |
744 next_trigger_delay); | 777 next_trigger - now); |
745 } | 778 } |
746 } | 779 } |
747 | 780 |
748 bool first_run_ = true; | 781 bool first_run_ = true; |
749 SwReporterInvocation invocation_; | 782 |
783 // The queue of invocations that are currently running. | |
784 SwReporterQueue current_invocations_; | |
785 | |
786 // The invocations to run next time the SwReporter is run. | |
787 SwReporterQueue pending_invocations_; | |
788 | |
750 base::Version version_; | 789 base::Version version_; |
751 scoped_refptr<base::TaskRunner> main_thread_task_runner_; | 790 scoped_refptr<base::TaskRunner> main_thread_task_runner_; |
752 scoped_refptr<base::TaskRunner> blocking_task_runner_; | 791 scoped_refptr<base::TaskRunner> blocking_task_runner_; |
753 | 792 |
754 // This value is used to identify how long to wait before starting a new run | 793 // This value is used to identify how long to wait before starting a new run |
755 // of the reporter. It's initialized with the default value and may be changed | 794 // of the reporter queue. It's initialized with the default value and may be |
756 // to a different value when a prompt is pending and the reporter should be | 795 // changed to a different value when a prompt is pending and the reporter |
757 // run before adding the global error to the Chrome menu. | 796 // should be run before adding the global error to the Chrome menu. |
758 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; | 797 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; |
759 | 798 |
760 // A single leaky instance. | 799 // A single leaky instance. |
761 static ReporterRunner* instance_; | 800 static ReporterRunner* instance_; |
762 | 801 |
763 DISALLOW_COPY_AND_ASSIGN(ReporterRunner); | 802 DISALLOW_COPY_AND_ASSIGN(ReporterRunner); |
764 }; | 803 }; |
765 | 804 |
766 ReporterRunner* ReporterRunner::instance_ = nullptr; | 805 ReporterRunner* ReporterRunner::instance_ = nullptr; |
767 | 806 |
(...skipping 11 matching lines...) Expand all Loading... | |
779 | 818 |
780 SwReporterInvocation SwReporterInvocation::FromCommandLine( | 819 SwReporterInvocation SwReporterInvocation::FromCommandLine( |
781 const base::CommandLine& command_line) { | 820 const base::CommandLine& command_line) { |
782 SwReporterInvocation invocation; | 821 SwReporterInvocation invocation; |
783 invocation.command_line = command_line; | 822 invocation.command_line = command_line; |
784 return invocation; | 823 return invocation; |
785 } | 824 } |
786 | 825 |
787 bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const { | 826 bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const { |
788 return command_line.argv() == other.command_line.argv() && | 827 return command_line.argv() == other.command_line.argv() && |
789 suffix == other.suffix && is_experimental == other.is_experimental; | 828 suffix == other.suffix && flags == other.flags; |
790 } | 829 } |
791 | 830 |
792 void RunSwReporter(const SwReporterInvocation& invocation, | 831 void RunSwReporters(const SwReporterQueue& invocations, |
793 const base::Version& version, | 832 const base::Version& version, |
794 scoped_refptr<base::TaskRunner> main_thread_task_runner, | 833 scoped_refptr<base::TaskRunner> main_thread_task_runner, |
795 scoped_refptr<base::TaskRunner> blocking_task_runner) { | 834 scoped_refptr<base::TaskRunner> blocking_task_runner) { |
796 ReporterRunner::Run(invocation, version, std::move(main_thread_task_runner), | 835 DCHECK(!invocations.empty()); |
797 std::move(blocking_task_runner)); | 836 ReporterRunner::ScheduleInvocations(invocations, version, |
837 std::move(main_thread_task_runner), | |
838 std::move(blocking_task_runner)); | |
798 } | 839 } |
799 | 840 |
800 bool ReporterFoundUws() { | 841 bool ReporterFoundUws() { |
801 PrefService* local_state = g_browser_process->local_state(); | 842 PrefService* local_state = g_browser_process->local_state(); |
802 if (!local_state) | 843 if (!local_state) |
803 return false; | 844 return false; |
804 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode); | 845 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode); |
805 return exit_code == kSwReporterCleanupNeeded; | 846 return exit_code == kSwReporterCleanupNeeded; |
806 } | 847 } |
807 | 848 |
808 bool UserHasRunCleaner() { | 849 bool UserHasRunCleaner() { |
809 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey); | 850 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey); |
810 cleaner_key_path.append(L"\\").append(kCleanerSubKey); | 851 cleaner_key_path.append(L"\\").append(kCleanerSubKey); |
811 | 852 |
812 base::win::RegKey srt_cleaner_key(HKEY_CURRENT_USER, cleaner_key_path.c_str(), | 853 base::win::RegKey srt_cleaner_key(HKEY_CURRENT_USER, cleaner_key_path.c_str(), |
813 KEY_QUERY_VALUE); | 854 KEY_QUERY_VALUE); |
814 | 855 |
815 return srt_cleaner_key.Valid() && srt_cleaner_key.GetValueCount() > 0; | 856 return srt_cleaner_key.Valid() && srt_cleaner_key.GetValueCount() > 0; |
816 } | 857 } |
817 | 858 |
818 void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate) { | 859 void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate) { |
819 g_testing_delegate_ = delegate; | 860 g_testing_delegate_ = delegate; |
820 } | 861 } |
821 | 862 |
822 } // namespace safe_browsing | 863 } // namespace safe_browsing |
OLD | NEW |