Index: chrome/browser/safe_browsing/srt_fetcher_win.cc |
diff --git a/chrome/browser/safe_browsing/srt_fetcher_win.cc b/chrome/browser/safe_browsing/srt_fetcher_win.cc |
index d46ed04482d957058e2e2d8c14b6c25a87122959..8a99316285f85b66c68e8a4ba01d4496fae1c962 100644 |
--- a/chrome/browser/safe_browsing/srt_fetcher_win.cc |
+++ b/chrome/browser/safe_browsing/srt_fetcher_win.cc |
@@ -119,7 +119,9 @@ const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed"; |
// Reports metrics about the software reporter via UMA (and sometimes Rappor). |
class UMAHistogramReporter { |
public: |
- explicit UMAHistogramReporter(const std::string& suffix = std::string()) |
+ UMAHistogramReporter() : UMAHistogramReporter(std::string()) {} |
+ |
+ explicit UMAHistogramReporter(const std::string& suffix) |
: suffix_(suffix), |
registry_key_(suffix.empty() ? kSoftwareRemovalToolRegistryKey |
: base::StringPrintf( |
@@ -588,20 +590,21 @@ void MaybeFetchSRT(Browser* browser, const base::Version& reporter_version) { |
class ReporterRunner : public chrome::BrowserListObserver { |
public: |
// Starts the sequence of attempts to run the reporter. |
grt (UTC plus 2)
2016/09/02 10:19:57
"reporters" (please update all comments accordingl
Joe Mason
2016/09/02 21:14:34
Done.
|
- static void Run(const SwReporterInvocation& invocation, |
+ static void Run(std::unique_ptr<SwReporterQueue> invocations, |
const base::Version& version, |
scoped_refptr<base::TaskRunner> main_thread_task_runner, |
scoped_refptr<base::TaskRunner> blocking_task_runner) { |
if (!instance_) |
instance_ = new ReporterRunner; |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ DCHECK(invocations); |
// There's nothing to do if the path and version of the reporter has not |
// changed, we just keep running the tasks that are running now. |
- if (instance_->invocation_ == invocation && instance_->version_.IsValid() && |
- instance_->version_ == version) |
+ if (instance_->invocations_ && *instance_->invocations_ == *invocations && |
grt (UTC plus 2)
2016/09/02 10:19:57
now that i've taken more time to grok ReporterRunn
Joe Mason
2016/09/02 21:14:35
I don't think this is any clearer than using a que
grt (UTC plus 2)
2016/09/04 10:35:44
yes, duplicate state is bad. could all state be in
macourteau
2016/09/12 19:53:15
Done.
|
+ instance_->version_.IsValid() && instance_->version_ == version) |
return; |
- instance_->invocation_ = invocation; |
+ instance_->invocations_ = std::move(invocations); |
instance_->version_ = version; |
instance_->main_thread_task_runner_ = std::move(main_thread_task_runner); |
instance_->blocking_task_runner_ = std::move(blocking_task_runner); |
@@ -626,12 +629,41 @@ class ReporterRunner : public chrome::BrowserListObserver { |
BrowserList::RemoveObserver(this); |
} |
+ // Launches the command line at the head of the queue. |
+ void LaunchNextInvocation(std::unique_ptr<SwReporterQueue> invocations) { |
grt (UTC plus 2)
2016/09/02 10:19:57
nit: "ScheduleNextInvocation" is more fitting
Joe Mason
2016/09/02 21:14:35
I disagree. It posts a task to do the (synchronous
grt (UTC plus 2)
2016/09/04 10:35:44
...which is another way of saying it schedules it
macourteau
2016/09/12 19:53:15
Done.
|
+ DCHECK(invocations); |
+ DCHECK(!invocations->empty()); |
+ auto next_invocation = invocations->front(); |
+ invocations->pop(); |
+ |
+ if (g_testing_delegate_) |
+ g_testing_delegate_->NotifyLaunchReady(); |
+ |
+ // It's OK to simply |PostTaskAndReplyWithResult| so that |
+ // |LaunchAndWaitForExit| doesn't need to access |main_thread_task_runner_| |
grt (UTC plus 2)
2016/09/02 10:19:58
i find the use of task runners for the main/UI thr
Joe Mason
2016/09/02 21:14:35
Agreed. But I don't think I should be changing the
grt (UTC plus 2)
2016/09/04 10:35:44
Ack.
|
+ // since the callback is not delayed and the test task runner won't need to |
+ // force it. |
+ base::PostTaskAndReplyWithResult( |
+ blocking_task_runner_.get(), FROM_HERE, |
+ |
+ // Send the head of the queue to the launch callback. |
+ base::Bind(&LaunchAndWaitForExit, next_invocation), |
+ |
+ // Send the tail of the queue to the next callback, which will handle |
+ // the results of the first launch and then recursively launch |
+ // everything in the tail. |
+ base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), |
+ base::Time::Now(), version_, next_invocation, |
+ base::Passed(std::move(invocations)))); |
+ } |
+ |
// This method is called on the UI thread when the reporter run has completed. |
grt (UTC plus 2)
2016/09/02 10:19:57
"the reporter" -> "a reporter"
Joe Mason
2016/09/02 21:14:34
Done.
|
// This is run as a task posted from an interruptible worker thread so should |
// be resilient to unexpected shutdown. |
void ReporterDone(const base::Time& reporter_start_time, |
const base::Version& version, |
const SwReporterInvocation& finished_invocation, |
+ std::unique_ptr<SwReporterQueue> remaining_invocations, |
int exit_code) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
@@ -640,24 +672,38 @@ class ReporterRunner : public chrome::BrowserListObserver { |
base::TimeDelta reporter_running_time = |
base::Time::Now() - reporter_start_time; |
- // Don't continue when the reporter process failed to launch, but still try |
- // again after the regular delay. It's not worth retrying earlier, risking |
- // running too often if it always fails, since not many users fail here. |
- main_thread_task_runner_->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), |
- base::TimeDelta::FromDays(days_between_reporter_runs_)); |
+ |
+ // Don't continue the current queue of reporters if one failed to launch. |
+ // As soon as we're not running this queue, schedule the next overall queue |
+ // run after the regular delay. (If there was a failure it's not worth |
+ // retrying earlier, risking running too often if it always fails, since |
+ // not many users fail here.) |
+ if (!remaining_invocations->empty() && |
+ exit_code != kReporterFailureExitCode) { |
+ LaunchNextInvocation(std::move(remaining_invocations)); |
+ } else { |
+ main_thread_task_runner_->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), |
+ base::TimeDelta::FromDays(days_between_reporter_runs_)); |
+ } |
+ |
+ // If the reporter failed to launch, do not process the results. (The exit |
+ // code itself doesn't need to be logged in this case because |
+ // SW_REPORTER_FAILED_TO_START is logged in |LaunchAndWaitForExit|.) |
if (exit_code == kReporterFailureExitCode) |
return; |
UMAHistogramReporter uma(finished_invocation.suffix); |
uma.ReportVersion(version); |
uma.ReportExitCode(exit_code); |
- uma.ReportFoundUwS(!finished_invocation.is_experimental /*use_rappor*/); |
+ uma.ReportFoundUwS(finished_invocation.flags & |
+ SwReporterInvocation::FLAG_LOG_TO_RAPPOR); |
// Only save results from the canonical version of the software. |
PrefService* local_state = g_browser_process->local_state(); |
- if (local_state && !finished_invocation.is_experimental) { |
+ if (local_state && |
+ (finished_invocation.flags & SwReporterInvocation::FLAG_LOG_TO_PREFS)) { |
local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code); |
local_state->SetInt64(prefs::kSwReporterLastTimeTriggered, |
base::Time::Now().ToInternalValue()); |
@@ -666,8 +712,8 @@ class ReporterRunner : public chrome::BrowserListObserver { |
uma.ReportScanTimes(); |
uma.ReportMemoryUsage(); |
- // Only continue to launch the prompt for the canonical version. |
- if (finished_invocation.is_experimental) |
+ if (!(finished_invocation.flags & |
+ SwReporterInvocation::FLAG_TRIGGER_PROMPT)) |
return; |
if (!IsInSRTPromptFieldTrialGroups()) { |
@@ -721,22 +767,16 @@ class ReporterRunner : public chrome::BrowserListObserver { |
last_time_triggered + |
base::TimeDelta::FromDays(days_between_reporter_runs_) - |
base::Time::Now()); |
- if (next_trigger_delay.ToInternalValue() <= 0 || |
- // Also make sure the kSwReporterLastTimeTriggered value is not set in |
- // the future. |
- last_time_triggered > base::Time::Now()) { |
- if (g_testing_delegate_) |
- g_testing_delegate_->NotifyLaunchReady(); |
- |
- // It's OK to simply |PostTaskAndReplyWithResult| so that |
- // |LaunchAndWaitForExit| doesn't need to access |
- // |main_thread_task_runner_| since the callback is not delayed and the |
- // test task runner won't need to force it. |
- base::PostTaskAndReplyWithResult( |
- blocking_task_runner_.get(), FROM_HERE, |
- base::Bind(&LaunchAndWaitForExit, invocation_), |
- base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), |
- base::Time::Now(), version_, invocation_)); |
+ DCHECK(invocations_); |
+ if (!invocations_->empty() && |
+ (next_trigger_delay.ToInternalValue() <= 0 || |
grt (UTC plus 2)
2016/09/02 10:19:57
don't convert a time or timedelta to its internal
Joe Mason
2016/09/02 21:14:35
Done.
|
+ // Also make sure the kSwReporterLastTimeTriggered value is not set in |
+ // the future. |
+ last_time_triggered > base::Time::Now())) { |
+ // Make a copy of the queue, since LaunchNextInvocation will pop items |
+ // from it. We need to save the full original for the comparison in |
+ // Run. |
+ LaunchNextInvocation(std::make_unique<SwReporterQueue>(*invocations_)); |
} else { |
main_thread_task_runner_->PostDelayedTask( |
FROM_HERE, |
@@ -746,7 +786,7 @@ class ReporterRunner : public chrome::BrowserListObserver { |
} |
bool first_run_ = true; |
- SwReporterInvocation invocation_; |
+ std::unique_ptr<SwReporterQueue> invocations_; |
base::Version version_; |
scoped_refptr<base::TaskRunner> main_thread_task_runner_; |
scoped_refptr<base::TaskRunner> blocking_task_runner_; |
@@ -786,14 +826,15 @@ SwReporterInvocation SwReporterInvocation::FromCommandLine( |
bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const { |
return command_line.argv() == other.command_line.argv() && |
- suffix == other.suffix && is_experimental == other.is_experimental; |
+ suffix == other.suffix && flags == other.flags; |
} |
-void RunSwReporter(const SwReporterInvocation& invocation, |
- const base::Version& version, |
- scoped_refptr<base::TaskRunner> main_thread_task_runner, |
- scoped_refptr<base::TaskRunner> blocking_task_runner) { |
- ReporterRunner::Run(invocation, version, std::move(main_thread_task_runner), |
+void RunSwReporters(std::unique_ptr<SwReporterQueue> invocations, |
+ const base::Version& version, |
+ scoped_refptr<base::TaskRunner> main_thread_task_runner, |
+ scoped_refptr<base::TaskRunner> blocking_task_runner) { |
+ ReporterRunner::Run(std::move(invocations), version, |
grt (UTC plus 2)
2016/09/02 10:19:58
? DCHECK(!invocations->empty());
why would it be
Joe Mason
2016/09/02 21:14:34
There's a DCHECK for that at the top of ReporterRu
grt (UTC plus 2)
2016/09/04 10:35:44
is there? i see one that DCHECKs that the pointer
macourteau
2016/09/12 19:53:15
Done.
|
+ std::move(main_thread_task_runner), |
std::move(blocking_task_runner)); |
} |