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

Side by Side Diff: chrome/browser/safe_browsing/srt_fetcher_win.cc

Issue 2226133005: Add support for the ExperimentalSwReporterEngine field trial. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Set flags explicitly in srt_fetcher browsertest Created 4 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
« no previous file with comments | « chrome/browser/safe_browsing/srt_fetcher_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <algorithm> 9 #include <algorithm>
10 #include <memory> 10 #include <memory>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
16 #include "base/callback_helpers.h" 16 #include "base/callback_helpers.h"
17 #include "base/command_line.h" 17 #include "base/command_line.h"
18 #include "base/debug/leak_annotations.h"
18 #include "base/files/file_path.h" 19 #include "base/files/file_path.h"
19 #include "base/macros.h" 20 #include "base/macros.h"
20 #include "base/metrics/field_trial.h" 21 #include "base/metrics/field_trial.h"
21 #include "base/metrics/histogram_macros.h" 22 #include "base/metrics/histogram_macros.h"
22 #include "base/metrics/sparse_histogram.h" 23 #include "base/metrics/sparse_histogram.h"
23 #include "base/process/launch.h" 24 #include "base/process/launch.h"
24 #include "base/strings/string_number_conversions.h" 25 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/stringprintf.h" 26 #include "base/strings/stringprintf.h"
26 #include "base/strings/utf_string_conversions.h" 27 #include "base/strings/utf_string_conversions.h"
27 #include "base/task_runner_util.h" 28 #include "base/task_runner_util.h"
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 123
123 const char kFoundUwsMetricName[] = "SoftwareReporter.FoundUwS"; 124 const char kFoundUwsMetricName[] = "SoftwareReporter.FoundUwS";
124 const char kFoundUwsReadErrorMetricName[] = 125 const char kFoundUwsReadErrorMetricName[] =
125 "SoftwareReporter.FoundUwSReadError"; 126 "SoftwareReporter.FoundUwSReadError";
126 const char kScanTimesMetricName[] = "SoftwareReporter.UwSScanTimes"; 127 const char kScanTimesMetricName[] = "SoftwareReporter.UwSScanTimes";
127 const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed"; 128 const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed";
128 129
129 // Reports metrics about the software reporter via UMA (and sometimes Rappor). 130 // Reports metrics about the software reporter via UMA (and sometimes Rappor).
130 class UMAHistogramReporter { 131 class UMAHistogramReporter {
131 public: 132 public:
132 explicit UMAHistogramReporter(const std::string& suffix = std::string()) 133 UMAHistogramReporter() : UMAHistogramReporter(std::string()) {}
134
135 explicit UMAHistogramReporter(const std::string& suffix)
133 : suffix_(suffix), 136 : suffix_(suffix),
134 registry_key_(suffix.empty() ? kSoftwareRemovalToolRegistryKey 137 registry_key_(suffix.empty() ? kSoftwareRemovalToolRegistryKey
135 : base::StringPrintf( 138 : base::StringPrintf(
136 L"%ls\\%ls", 139 L"%ls\\%ls",
137 kSoftwareRemovalToolRegistryKey, 140 kSoftwareRemovalToolRegistryKey,
138 base::UTF8ToUTF16(suffix).c_str())) { 141 base::UTF8ToUTF16(suffix).c_str())) {
139 } 142 }
140 143
141 // Reports the software reporter tool's version via UMA. 144 // Reports the software reporter tool's version via UMA.
142 void ReportVersion(const base::Version& version) const { 145 void ReportVersion(const base::Version& version) const {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 reporter_key.DeleteValue(kMemoryUsedValueName); 221 reporter_key.DeleteValue(kMemoryUsedValueName);
219 } 222 }
220 } 223 }
221 224
222 // Reports the SwReporter run time with UMA both as reported by the tool via 225 // Reports the SwReporter run time with UMA both as reported by the tool via
223 // the registry and as measured by |ReporterRunner|. 226 // the registry and as measured by |ReporterRunner|.
224 void ReportRuntime(const base::TimeDelta& reporter_running_time) const { 227 void ReportRuntime(const base::TimeDelta& reporter_running_time) const {
225 RecordLongTimesHistogram("SoftwareReporter.RunningTimeAccordingToChrome", 228 RecordLongTimesHistogram("SoftwareReporter.RunningTimeAccordingToChrome",
226 reporter_running_time); 229 reporter_running_time);
227 230
231 // TODO(b/641081): This should only have KEY_QUERY_VALUE and KEY_SET_VALUE,
232 // and use Open to avoid creating the key if it doesn't already exist.
228 base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(), 233 base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(),
229 KEY_ALL_ACCESS); 234 KEY_ALL_ACCESS);
230 if (!reporter_key.Valid()) { 235 if (!reporter_key.Valid()) {
231 RecordEnumerationHistogram( 236 RecordEnumerationHistogram(
232 kRunningTimeErrorMetricName, 237 kRunningTimeErrorMetricName,
233 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID, 238 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID,
234 REPORTER_RUNNING_TIME_ERROR_MAX); 239 REPORTER_RUNNING_TIME_ERROR_MAX);
235 return; 240 return;
236 } 241 }
237 242
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 RecordEnumerationHistogram(kRunningTimeErrorMetricName, 280 RecordEnumerationHistogram(kRunningTimeErrorMetricName,
276 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME, 281 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME,
277 REPORTER_RUNNING_TIME_ERROR_MAX); 282 REPORTER_RUNNING_TIME_ERROR_MAX);
278 } 283 }
279 } 284 }
280 285
281 // Reports the UwS scan times of the software reporter tool via UMA. 286 // Reports the UwS scan times of the software reporter tool via UMA.
282 void ReportScanTimes() const { 287 void ReportScanTimes() const {
283 base::string16 scan_times_key_path = base::StringPrintf( 288 base::string16 scan_times_key_path = base::StringPrintf(
284 L"%ls\\%ls", registry_key_.c_str(), kScanTimesSubKey); 289 L"%ls\\%ls", registry_key_.c_str(), kScanTimesSubKey);
290 // TODO(b/641081): This should only have KEY_QUERY_VALUE and KEY_SET_VALUE,
291 // and use Open to avoid creating the key if it doesn't already exist.
285 base::win::RegKey scan_times_key( 292 base::win::RegKey scan_times_key(
286 HKEY_CURRENT_USER, scan_times_key_path.c_str(), KEY_ALL_ACCESS); 293 HKEY_CURRENT_USER, scan_times_key_path.c_str(), KEY_ALL_ACCESS);
287 if (!scan_times_key.Valid()) 294 if (!scan_times_key.Valid())
288 return; 295 return;
289 296
290 base::string16 value_name; 297 base::string16 value_name;
291 int uws_id = 0; 298 int uws_id = 0;
292 int64_t raw_scan_time = 0; 299 int64_t raw_scan_time = 0;
293 int num_scan_times = scan_times_key.GetValueCount(); 300 int num_scan_times = scan_times_key.GetValueCount();
294 for (int i = 0; i < num_scan_times; ++i) { 301 for (int i = 0; i < num_scan_times; ++i) {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 prefs->SetString(prefs::kSwReporterPromptVersion, 608 prefs->SetString(prefs::kSwReporterPromptVersion,
602 reporter_version.GetString()); 609 reporter_version.GetString());
603 610
604 // Download the SRT. 611 // Download the SRT.
605 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START); 612 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START);
606 613
607 // All the work happens in the self-deleting class below. 614 // All the work happens in the self-deleting class below.
608 new SRTFetcher(profile); 615 new SRTFetcher(profile);
609 } 616 }
610 617
611 // This class tries to run the reporter and reacts to its exit code. It 618 // This class tries to run a queue of reporters and react to their exit codes.
612 // schedules subsequent runs as needed, or retries as soon as a browser is 619 // It schedules subsequent runs of the queue as needed, or retries as soon as a
613 // available when none is on first try. 620 // browser is available when none is on first try.
614 class ReporterRunner : public chrome::BrowserListObserver { 621 class ReporterRunner : public chrome::BrowserListObserver {
615 public: 622 public:
616 // Starts the sequence of attempts to run the reporter. 623 // Registers |invocations| to run next time |TryToRun| is scheduled. (And if
617 static void Run(const SwReporterInvocation& invocation, 624 // it's not already scheduled, call it now.)
618 const base::Version& version, 625 static void ScheduleInvocations(
619 scoped_refptr<base::TaskRunner> main_thread_task_runner, 626 const SwReporterQueue& invocations,
620 scoped_refptr<base::TaskRunner> blocking_task_runner) { 627 const base::Version& version,
621 if (!instance_) 628 scoped_refptr<base::TaskRunner> main_thread_task_runner,
629 scoped_refptr<base::TaskRunner> blocking_task_runner) {
630 if (!instance_) {
622 instance_ = new ReporterRunner; 631 instance_ = new ReporterRunner;
632 ANNOTATE_LEAKING_OBJECT_PTR(instance_);
633 }
623 DCHECK_CURRENTLY_ON(BrowserThread::UI); 634 DCHECK_CURRENTLY_ON(BrowserThread::UI);
624 // There's nothing to do if the path and version of the reporter has not 635
625 // changed, we just keep running the tasks that are running now. 636 // There's nothing to do if the invocation parameters and version of the
626 if (instance_->invocation_ == invocation && instance_->version_.IsValid() && 637 // reporter have not changed, we just keep running the tasks that are
627 instance_->version_ == version) 638 // running now.
639 if (instance_->pending_invocations_ == invocations &&
640 instance_->version_.IsValid() && instance_->version_ == version)
628 return; 641 return;
629 642
630 instance_->invocation_ = invocation; 643 instance_->pending_invocations_ = invocations;
631 instance_->version_ = version; 644 instance_->version_ = version;
632 instance_->main_thread_task_runner_ = std::move(main_thread_task_runner); 645 instance_->main_thread_task_runner_ = std::move(main_thread_task_runner);
633 instance_->blocking_task_runner_ = std::move(blocking_task_runner); 646 instance_->blocking_task_runner_ = std::move(blocking_task_runner);
634 647
635 if (instance_->first_run_) { 648 if (instance_->first_run_) {
636 instance_->first_run_ = false; 649 instance_->first_run_ = false;
637 instance_->TryToRun(); 650 instance_->TryToRun();
638 } 651 }
639 } 652 }
640 653
641 private: 654 private:
642 ReporterRunner() {} 655 ReporterRunner() {}
643 ~ReporterRunner() override {} 656 ~ReporterRunner() override {}
644 657
645 // BrowserListObserver. 658 // BrowserListObserver.
646 void OnBrowserSetLastActive(Browser* browser) override {} 659 void OnBrowserSetLastActive(Browser* browser) override {}
647 void OnBrowserRemoved(Browser* browser) override {} 660 void OnBrowserRemoved(Browser* browser) override {}
648 void OnBrowserAdded(Browser* browser) override { 661 void OnBrowserAdded(Browser* browser) override {
649 DCHECK_CURRENTLY_ON(BrowserThread::UI); 662 DCHECK_CURRENTLY_ON(BrowserThread::UI);
650 DCHECK(browser); 663 DCHECK(browser);
651 MaybeFetchSRT(browser, version_); 664 MaybeFetchSRT(browser, version_);
652 BrowserList::RemoveObserver(this); 665 BrowserList::RemoveObserver(this);
653 } 666 }
654 667
655 // This method is called on the UI thread when the reporter run has completed. 668 // Launches the command line at the head of the queue.
656 // This is run as a task posted from an interruptible worker thread so should 669 void ScheduleNextInvocation() {
657 // be resilient to unexpected shutdown. 670 DCHECK(!current_invocations_.empty());
671 auto next_invocation = current_invocations_.front();
672 current_invocations_.pop();
673
674 if (g_testing_delegate_)
675 g_testing_delegate_->NotifyLaunchReady();
676
677 // Add switches for users who opted into extended Safe Browsing reporting.
678 // The invocation object is changed locally right before the actual process
679 // is launched because user status can change between this and the next run
680 // for this ReporterRunner object. For example, the ReporterDone() callback
681 // schedules the next run for a few days later, and the user might have
682 // changed settings in the meantime.
683 PrefService* local_state = g_browser_process->local_state();
684 if (next_invocation.flags & SwReporterInvocation::FLAG_SEND_REPORTER_LOGS &&
685 local_state && ShouldSendReporterLogs(*local_state)) {
686 AddSwitchesForExtendedReporterUser(&next_invocation);
687 // Set the local state value before the first attempt to run the
688 // reporter, because we only want to upload logs once in the window
689 // defined by |kDaysBetweenReporterLogsSent|. If we set with other local
690 // state values after the reporter runs, we could send logs again too
691 // quickly (for example, if Chrome stops before the reporter finishes).
692 local_state->SetInt64(prefs::kSwReporterLastTimeSentReport,
693 base::Time::Now().ToInternalValue());
694 }
695
696 // It's OK to simply |PostTaskAndReplyWithResult| so that
697 // |LaunchAndWaitForExit| doesn't need to access |main_thread_task_runner_|
698 // since the callback is not delayed and the test task runner won't need to
699 // force it.
700 base::PostTaskAndReplyWithResult(
701 blocking_task_runner_.get(), FROM_HERE,
702 base::Bind(&LaunchAndWaitForExit, next_invocation),
703 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this),
704 base::Time::Now(), version_, next_invocation));
705 }
706
707 // This method is called on the UI thread when an invocation of the reporter
708 // has completed. This is run as a task posted from an interruptible worker
709 // thread so should be resilient to unexpected shutdown.
658 void ReporterDone(const base::Time& reporter_start_time, 710 void ReporterDone(const base::Time& reporter_start_time,
659 const base::Version& version, 711 const base::Version& version,
660 const SwReporterInvocation& finished_invocation, 712 const SwReporterInvocation& finished_invocation,
661 int exit_code) { 713 int exit_code) {
662 DCHECK_CURRENTLY_ON(BrowserThread::UI); 714 DCHECK_CURRENTLY_ON(BrowserThread::UI);
663 715
664 if (g_testing_delegate_) 716 if (g_testing_delegate_)
665 g_testing_delegate_->NotifyReporterDone(); 717 g_testing_delegate_->NotifyReporterDone();
666 718
667 base::TimeDelta reporter_running_time = 719 base::TimeDelta reporter_running_time =
668 base::Time::Now() - reporter_start_time; 720 base::Time::Now() - reporter_start_time;
669 // Don't continue when the reporter process failed to launch, but still try 721
670 // again after the regular delay. It's not worth retrying earlier, risking 722 // Don't continue the current queue of reporters if one failed to launch.
671 // running too often if it always fails, since not many users fail here. 723 if (exit_code == kReporterFailureExitCode)
672 main_thread_task_runner_->PostDelayedTask( 724 current_invocations_ = SwReporterQueue();
673 FROM_HERE, 725
674 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), 726 // As soon as we're not running this queue, schedule the next overall queue
675 base::TimeDelta::FromDays(days_between_reporter_runs_)); 727 // run after the regular delay. (If there was a failure it's not worth
728 // retrying earlier, risking running too often if it always fails, since
729 // not many users fail here.)
730 if (current_invocations_.empty()) {
731 main_thread_task_runner_->PostDelayedTask(
732 FROM_HERE,
733 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)),
734 base::TimeDelta::FromDays(days_between_reporter_runs_));
735 } else {
736 ScheduleNextInvocation();
737 }
738
739 // If the reporter failed to launch, do not process the results. (The exit
740 // code itself doesn't need to be logged in this case because
741 // SW_REPORTER_FAILED_TO_START is logged in |LaunchAndWaitForExit|.)
676 if (exit_code == kReporterFailureExitCode) 742 if (exit_code == kReporterFailureExitCode)
677 return; 743 return;
678 744
679 UMAHistogramReporter uma(finished_invocation.suffix); 745 UMAHistogramReporter uma(finished_invocation.suffix);
680 uma.ReportVersion(version); 746 uma.ReportVersion(version);
681 uma.ReportExitCode(exit_code); 747 uma.ReportExitCode(exit_code);
682 uma.ReportFoundUwS(!finished_invocation.is_experimental /*use_rappor*/); 748 uma.ReportFoundUwS(finished_invocation.flags &
749 SwReporterInvocation::FLAG_LOG_TO_RAPPOR);
683 750
684 // Only save results from the canonical version of the software.
685 PrefService* local_state = g_browser_process->local_state(); 751 PrefService* local_state = g_browser_process->local_state();
686 if (local_state && !finished_invocation.is_experimental) { 752 if (local_state) {
687 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code); 753 if (finished_invocation.flags &
754 SwReporterInvocation::FLAG_LOG_EXIT_CODE_TO_PREFS)
755 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code);
688 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered, 756 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered,
689 base::Time::Now().ToInternalValue()); 757 base::Time::Now().ToInternalValue());
690 } 758 }
691 uma.ReportRuntime(reporter_running_time); 759 uma.ReportRuntime(reporter_running_time);
692 uma.ReportScanTimes(); 760 uma.ReportScanTimes();
693 uma.ReportMemoryUsage(); 761 uma.ReportMemoryUsage();
694 762
695 // Only continue to launch the prompt for the canonical version. 763 if (!(finished_invocation.flags &
696 if (finished_invocation.is_experimental) 764 SwReporterInvocation::FLAG_TRIGGER_PROMPT))
697 return; 765 return;
698 766
699 if (!IsInSRTPromptFieldTrialGroups()) { 767 if (!IsInSRTPromptFieldTrialGroups()) {
700 // Knowing about disabled field trial is more important than reporter not 768 // Knowing about disabled field trial is more important than reporter not
701 // finding anything to remove, so check this case first. 769 // finding anything to remove, so check this case first.
702 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL); 770 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL);
703 return; 771 return;
704 } 772 }
705 773
706 if (exit_code != kSwReporterPostRebootCleanupNeeded && 774 if (exit_code != kSwReporterPostRebootCleanupNeeded &&
(...skipping 13 matching lines...) Expand all
720 RecordReporterStepHistogram(SW_REPORTER_NO_BROWSER); 788 RecordReporterStepHistogram(SW_REPORTER_NO_BROWSER);
721 BrowserList::AddObserver(this); 789 BrowserList::AddObserver(this);
722 } else { 790 } else {
723 MaybeFetchSRT(browser, version_); 791 MaybeFetchSRT(browser, version_);
724 } 792 }
725 } 793 }
726 794
727 void TryToRun() { 795 void TryToRun() {
728 DCHECK_CURRENTLY_ON(BrowserThread::UI); 796 DCHECK_CURRENTLY_ON(BrowserThread::UI);
729 PrefService* local_state = g_browser_process->local_state(); 797 PrefService* local_state = g_browser_process->local_state();
798
730 if (!version_.IsValid() || !local_state) { 799 if (!version_.IsValid() || !local_state) {
800 // TODO(b/641081): This doesn't look right. Even on first run, |version_|
801 // should be valid (and this is already checked in RunSwReporters). We
802 // should abort if local_state is missing, but this has nothing to do
803 // with |first_run_|.
731 DCHECK(first_run_); 804 DCHECK(first_run_);
732 return; 805 return;
733 } 806 }
734 807
735 // Run the reporter if it hasn't been triggered in the last 808 // Run a queue of reporters if none have been triggered in the last
736 // |days_between_reporter_runs_| days, which depends if there is a pending 809 // |days_between_reporter_runs_| days, which depends if there is a pending
737 // prompt to be added to Chrome's menu. 810 // prompt to be added to Chrome's menu.
738 if (local_state->GetBoolean(prefs::kSwReporterPendingPrompt)) { 811 if (local_state->GetBoolean(prefs::kSwReporterPendingPrompt)) {
739 days_between_reporter_runs_ = kDaysBetweenSwReporterRunsForPendingPrompt; 812 days_between_reporter_runs_ = kDaysBetweenSwReporterRunsForPendingPrompt;
740 RecordReporterStepHistogram(SW_REPORTER_RAN_DAILY); 813 RecordReporterStepHistogram(SW_REPORTER_RAN_DAILY);
741 } else { 814 } else {
742 days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; 815 days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns;
743 } 816 }
817 const base::Time now = base::Time::Now();
744 const base::Time last_time_triggered = base::Time::FromInternalValue( 818 const base::Time last_time_triggered = base::Time::FromInternalValue(
745 local_state->GetInt64(prefs::kSwReporterLastTimeTriggered)); 819 local_state->GetInt64(prefs::kSwReporterLastTimeTriggered));
746 base::TimeDelta next_trigger_delay( 820 const base::Time next_trigger(
747 last_time_triggered + 821 last_time_triggered +
748 base::TimeDelta::FromDays(days_between_reporter_runs_) - 822 base::TimeDelta::FromDays(days_between_reporter_runs_));
749 base::Time::Now()); 823 if (!pending_invocations_.empty() &&
750 if (next_trigger_delay.ToInternalValue() <= 0 || 824 (next_trigger <= now ||
751 // Also make sure the kSwReporterLastTimeTriggered value is not set in 825 // Also make sure the kSwReporterLastTimeTriggered value is not set in
752 // the future. 826 // the future.
753 last_time_triggered > base::Time::Now()) { 827 last_time_triggered > now)) {
754 if (g_testing_delegate_) 828 DCHECK(current_invocations_.empty());
755 g_testing_delegate_->NotifyLaunchReady(); 829 current_invocations_ = pending_invocations_;
756 830 ScheduleNextInvocation();
757 // Creating a new invocation to add switches for users who opted into
758 // extended Safe Browsing reporting. The invocation object is changed
759 // locally right before the actual process is launched because user status
760 // can change between this and the next run for this ReporterRunner
761 // object. For example, the ReporterDone() callback schedules the next run
762 // for a few days later, and the user might have changed settings in the
763 // meantime.
764 SwReporterInvocation actual_invocation(invocation_);
765 if (ShouldSendReporterLogs(*local_state)) {
766 AddSwitchesForExtendedReporterUser(&actual_invocation);
767 // Set the local state value before the first attempt to run the
768 // reporter, because we only want to upload logs once in the window
769 // defined by |kDaysBetweenReporterLogsSent|. If we set with other local
770 // state values after the reporter runs, we could send logs again too
771 // quickly (for example, if Chrome stops before the reporter finishes).
772 local_state->SetInt64(prefs::kSwReporterLastTimeSentReport,
773 base::Time::Now().ToInternalValue());
774 }
775 // It's OK to simply |PostTaskAndReplyWithResult| so that
776 // |LaunchAndWaitForExit| doesn't need to access
777 // |main_thread_task_runner_| since the callback is not delayed and the
778 // test task runner won't need to force it.
779 base::PostTaskAndReplyWithResult(
780 blocking_task_runner_.get(), FROM_HERE,
781 base::Bind(&LaunchAndWaitForExit, actual_invocation),
782 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this),
783 base::Time::Now(), version_, invocation_));
784 } else { 831 } else {
785 main_thread_task_runner_->PostDelayedTask( 832 main_thread_task_runner_->PostDelayedTask(
786 FROM_HERE, 833 FROM_HERE,
787 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), 834 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)),
788 next_trigger_delay); 835 next_trigger - now);
789 } 836 }
790 } 837 }
791 838
792 // Returns true if the experiment to send reporter logs is enabled, the user 839 // Returns true if the experiment to send reporter logs is enabled, the user
793 // opted into Safe Browsing extended reporting, and logs have been sent at 840 // opted into Safe Browsing extended reporting, and logs have been sent at
794 // least |kSwReporterLastTimeSentReport| days ago. 841 // least |kSwReporterLastTimeSentReport| days ago.
795 bool ShouldSendReporterLogs(const PrefService& local_state) { 842 bool ShouldSendReporterLogs(const PrefService& local_state) {
796 if (!base::FeatureList::IsEnabled(kSwReporterExtendedSafeBrowsingFeature) || 843 if (!base::FeatureList::IsEnabled(kSwReporterExtendedSafeBrowsingFeature) ||
797 !SafeBrowsingExtendedReportingEnabled()) { 844 !SafeBrowsingExtendedReportingEnabled()) {
798 return false; 845 return false;
(...skipping 15 matching lines...) Expand all
814 861
815 void AddSwitchesForExtendedReporterUser(SwReporterInvocation* invocation) { 862 void AddSwitchesForExtendedReporterUser(SwReporterInvocation* invocation) {
816 invocation->command_line.AppendSwitch(kExtendedSafeBrowsingEnabledSwitch); 863 invocation->command_line.AppendSwitch(kExtendedSafeBrowsingEnabledSwitch);
817 invocation->command_line.AppendSwitchASCII( 864 invocation->command_line.AppendSwitchASCII(
818 kChromeVersionSwitch, version_info::GetVersionNumber()); 865 kChromeVersionSwitch, version_info::GetVersionNumber());
819 invocation->command_line.AppendSwitchNative( 866 invocation->command_line.AppendSwitchNative(
820 kChromeChannelSwitch, base::IntToString16(ChannelAsInt())); 867 kChromeChannelSwitch, base::IntToString16(ChannelAsInt()));
821 } 868 }
822 869
823 bool first_run_ = true; 870 bool first_run_ = true;
824 SwReporterInvocation invocation_; 871
872 // The queue of invocations that are currently running.
873 SwReporterQueue current_invocations_;
874
875 // The invocations to run next time the SwReporter is run.
876 SwReporterQueue pending_invocations_;
877
825 base::Version version_; 878 base::Version version_;
826 scoped_refptr<base::TaskRunner> main_thread_task_runner_; 879 scoped_refptr<base::TaskRunner> main_thread_task_runner_;
827 scoped_refptr<base::TaskRunner> blocking_task_runner_; 880 scoped_refptr<base::TaskRunner> blocking_task_runner_;
828 881
829 // This value is used to identify how long to wait before starting a new run 882 // This value is used to identify how long to wait before starting a new run
830 // of the reporter. It's initialized with the default value and may be changed 883 // of the reporter queue. It's initialized with the default value and may be
831 // to a different value when a prompt is pending and the reporter should be 884 // changed to a different value when a prompt is pending and the reporter
832 // run before adding the global error to the Chrome menu. 885 // should be run before adding the global error to the Chrome menu.
833 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; 886 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns;
834 887
835 // A single leaky instance. 888 // A single leaky instance.
836 static ReporterRunner* instance_; 889 static ReporterRunner* instance_;
837 890
838 DISALLOW_COPY_AND_ASSIGN(ReporterRunner); 891 DISALLOW_COPY_AND_ASSIGN(ReporterRunner);
839 }; 892 };
840 893
841 ReporterRunner* ReporterRunner::instance_ = nullptr; 894 ReporterRunner* ReporterRunner::instance_ = nullptr;
842 895
843 } // namespace 896 } // namespace
844 897
845 SwReporterInvocation::SwReporterInvocation() 898 SwReporterInvocation::SwReporterInvocation()
846 : command_line(base::CommandLine::NO_PROGRAM) {} 899 : command_line(base::CommandLine::NO_PROGRAM) {}
847 900
848 SwReporterInvocation::SwReporterInvocation(const SwReporterInvocation& other)
849 : command_line(other.command_line),
850 suffix(other.suffix),
851 is_experimental(other.is_experimental) {}
852
853 SwReporterInvocation SwReporterInvocation::FromFilePath( 901 SwReporterInvocation SwReporterInvocation::FromFilePath(
854 const base::FilePath& exe_path) { 902 const base::FilePath& exe_path) {
855 SwReporterInvocation invocation; 903 SwReporterInvocation invocation;
856 invocation.command_line = base::CommandLine(exe_path); 904 invocation.command_line = base::CommandLine(exe_path);
857 return invocation; 905 return invocation;
858 } 906 }
859 907
860 SwReporterInvocation SwReporterInvocation::FromCommandLine( 908 SwReporterInvocation SwReporterInvocation::FromCommandLine(
861 const base::CommandLine& command_line) { 909 const base::CommandLine& command_line) {
862 SwReporterInvocation invocation; 910 SwReporterInvocation invocation;
863 invocation.command_line = command_line; 911 invocation.command_line = command_line;
864 return invocation; 912 return invocation;
865 } 913 }
866 914
867 bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const { 915 bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const {
868 return command_line.argv() == other.command_line.argv() && 916 return command_line.argv() == other.command_line.argv() &&
869 suffix == other.suffix && is_experimental == other.is_experimental; 917 suffix == other.suffix && flags == other.flags;
870 } 918 }
871 919
872 void RunSwReporter(const SwReporterInvocation& invocation, 920 void RunSwReporters(const SwReporterQueue& invocations,
873 const base::Version& version, 921 const base::Version& version,
874 scoped_refptr<base::TaskRunner> main_thread_task_runner, 922 scoped_refptr<base::TaskRunner> main_thread_task_runner,
875 scoped_refptr<base::TaskRunner> blocking_task_runner) { 923 scoped_refptr<base::TaskRunner> blocking_task_runner) {
876 ReporterRunner::Run(invocation, version, std::move(main_thread_task_runner), 924 DCHECK(!invocations.empty());
877 std::move(blocking_task_runner)); 925 DCHECK(version.IsValid());
926 ReporterRunner::ScheduleInvocations(invocations, version,
927 std::move(main_thread_task_runner),
928 std::move(blocking_task_runner));
878 } 929 }
879 930
880 bool ReporterFoundUws() { 931 bool ReporterFoundUws() {
881 PrefService* local_state = g_browser_process->local_state(); 932 PrefService* local_state = g_browser_process->local_state();
882 if (!local_state) 933 if (!local_state)
883 return false; 934 return false;
884 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode); 935 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode);
885 return exit_code == kSwReporterCleanupNeeded; 936 return exit_code == kSwReporterCleanupNeeded;
886 } 937 }
887 938
888 bool UserHasRunCleaner() { 939 bool UserHasRunCleaner() {
889 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey); 940 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey);
890 cleaner_key_path.append(L"\\").append(kCleanerSubKey); 941 cleaner_key_path.append(L"\\").append(kCleanerSubKey);
891 942
892 base::win::RegKey srt_cleaner_key(HKEY_CURRENT_USER, cleaner_key_path.c_str(), 943 base::win::RegKey srt_cleaner_key(HKEY_CURRENT_USER, cleaner_key_path.c_str(),
893 KEY_QUERY_VALUE); 944 KEY_QUERY_VALUE);
894 945
895 return srt_cleaner_key.Valid() && srt_cleaner_key.GetValueCount() > 0; 946 return srt_cleaner_key.Valid() && srt_cleaner_key.GetValueCount() > 0;
896 } 947 }
897 948
898 void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate) { 949 void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate) {
899 g_testing_delegate_ = delegate; 950 g_testing_delegate_ = delegate;
900 } 951 }
901 952
902 } // namespace safe_browsing 953 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/srt_fetcher_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698