| 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 208d8e5596ce76959cda565106edda832f16ccd0..ae23ee9ff906cd9c512f1103b9e1e2ed1ef006b0 100644
|
| --- a/chrome/browser/safe_browsing/srt_fetcher_win.cc
|
| +++ b/chrome/browser/safe_browsing/srt_fetcher_win.cc
|
| @@ -7,6 +7,7 @@
|
| #include <stdint.h>
|
|
|
| #include <memory>
|
| +#include <queue>
|
| #include <vector>
|
|
|
| #include "base/bind.h"
|
| @@ -16,7 +17,7 @@
|
| #include "base/files/file_path.h"
|
| #include "base/macros.h"
|
| #include "base/metrics/field_trial.h"
|
| -#include "base/metrics/histogram_macros.h"
|
| +#include "base/metrics/histogram.h"
|
| #include "base/metrics/sparse_histogram.h"
|
| #include "base/process/launch.h"
|
| #include "base/strings/string_number_conversions.h"
|
| @@ -120,8 +121,20 @@ const char kScanTimesMetricName[] = "SoftwareReporter.UwSScanTimes";
|
| const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed";
|
|
|
| // Reports metrics about the software reporter via UMA (and sometimes Rappor).
|
| +//
|
| +// This will format the names of the histograms at runtime by adding an
|
| +// optional suffix, so the UMA_HISTOGRAM macros won't work. Use RecordHistogram
|
| +// and related helper methods instead.
|
| class UMAHistogramReporter {
|
| public:
|
| + UMAHistogramReporter(const std::string& suffix = std::string())
|
| + : suffix_(suffix),
|
| + registry_key_(suffix.empty()
|
| + ? kSoftwareRemovalToolRegistryKey
|
| + : base::StringPrintf(L"%s\\%s",
|
| + kSoftwareRemovalToolRegistryKey,
|
| + base::UTF8ToUTF16(suffix))) {}
|
| +
|
| // Reports the software reporter tool's version via UMA.
|
| void ReportVersion(const base::Version& version) const {
|
| DCHECK(!version.components().empty());
|
| @@ -132,7 +145,7 @@ class UMAHistogramReporter {
|
| minor_version = version.components()[version.components().size() - 2];
|
| else
|
| minor_version = version.components()[0];
|
| - UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MinorVersion", minor_version);
|
| + RecordSparseHistogram("SoftwareReporter.MinorVersion", minor_version);
|
|
|
| // The major version for X.Y.Z is X*256^3+Y*256+Z. If there are additional
|
| // components, only the first three count, and if there are less than 3, the
|
| @@ -147,31 +160,31 @@ class UMAHistogramReporter {
|
| DCHECK_LT(version.components()[2], 0x100U);
|
| major_version += version.components()[2];
|
| }
|
| - UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MajorVersion", major_version);
|
| + RecordSparseHistogram("SoftwareReporter.MajorVersion", major_version);
|
| }
|
|
|
| void ReportExitCode(int exit_code) const {
|
| - UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code);
|
| + RecordSparseHistogram("SoftwareReporter.ExitCode", exit_code);
|
| }
|
|
|
| // Reports UwS found by the software reporter tool via UMA and RAPPOR.
|
| - void ReportFoundUwS() const {
|
| - base::win::RegKey reporter_key(HKEY_CURRENT_USER,
|
| - kSoftwareRemovalToolRegistryKey,
|
| + void ReportFoundUwS(bool use_rappor) const {
|
| + base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(),
|
| KEY_QUERY_VALUE | KEY_SET_VALUE);
|
| std::vector<base::string16> found_uws_strings;
|
| if (reporter_key.Valid() &&
|
| reporter_key.ReadValues(kFoundUwsValueName, &found_uws_strings) ==
|
| ERROR_SUCCESS) {
|
| - rappor::RapporService* rappor_service =
|
| - g_browser_process->rappor_service();
|
| + rappor::RapporService* rappor_service = nullptr;
|
| + if (use_rappor)
|
| + rappor_service = g_browser_process->rappor_service();
|
|
|
| bool parse_error = false;
|
| for (const base::string16& uws_string : found_uws_strings) {
|
| // All UwS ids are expected to be integers.
|
| uint32_t uws_id = 0;
|
| if (base::StringToUint(uws_string, &uws_id)) {
|
| - UMA_HISTOGRAM_SPARSE_SLOWLY(kFoundUwsMetricName, uws_id);
|
| + RecordSparseHistogram(kFoundUwsMetricName, uws_id);
|
| if (rappor_service) {
|
| rappor_service->RecordSample(kFoundUwsMetricName,
|
| rappor::COARSE_RAPPOR_TYPE,
|
| @@ -185,7 +198,7 @@ class UMAHistogramReporter {
|
| // Clean up the old value.
|
| reporter_key.DeleteValue(kFoundUwsValueName);
|
|
|
| - UMA_HISTOGRAM_BOOLEAN(kFoundUwsReadErrorMetricName, parse_error);
|
| + RecordBooleanHistogram(kFoundUwsReadErrorMetricName, parse_error);
|
| }
|
| }
|
|
|
| @@ -193,14 +206,13 @@ class UMAHistogramReporter {
|
| // by
|
| // the tool itself in the Windows registry.
|
| void ReportMemoryUsage() const {
|
| - base::win::RegKey reporter_key(HKEY_CURRENT_USER,
|
| - kSoftwareRemovalToolRegistryKey,
|
| + base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(),
|
| KEY_QUERY_VALUE | KEY_SET_VALUE);
|
| DWORD memory_used = 0;
|
| if (reporter_key.Valid() &&
|
| reporter_key.ReadValueDW(kMemoryUsedValueName, &memory_used) ==
|
| ERROR_SUCCESS) {
|
| - UMA_HISTOGRAM_MEMORY_KB(kMemoryUsedMetricName, memory_used);
|
| + RecordMemoryKBHistogram(kMemoryUsedMetricName, memory_used);
|
| reporter_key.DeleteValue(kMemoryUsedValueName);
|
| }
|
| }
|
| @@ -208,13 +220,13 @@ class UMAHistogramReporter {
|
| // Report the SwReporter run time with UMA both as reported by the tool via
|
| // the registry and as measured by |ReporterRunner|.
|
| void ReportRuntime(const base::TimeDelta& reporter_running_time) const {
|
| - UMA_HISTOGRAM_LONG_TIMES("SoftwareReporter.RunningTimeAccordingToChrome",
|
| + RecordLongTimesHistogram("SoftwareReporter.RunningTimeAccordingToChrome",
|
| reporter_running_time);
|
|
|
| - base::win::RegKey reporter_key(
|
| - HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_ALL_ACCESS);
|
| + base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(),
|
| + KEY_ALL_ACCESS);
|
| if (!reporter_key.Valid()) {
|
| - UMA_HISTOGRAM_ENUMERATION(
|
| + RecordEnumerationHistogram(
|
| kRunningTimeErrorMetricName,
|
| REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID,
|
| REPORTER_RUNNING_TIME_ERROR_MAX);
|
| @@ -243,31 +255,31 @@ class UMAHistogramReporter {
|
| base::TimeDelta registry_run_time =
|
| base::Time::FromInternalValue(end_time_value) -
|
| base::Time::FromInternalValue(start_time_value);
|
| - UMA_HISTOGRAM_LONG_TIMES("SoftwareReporter.RunningTime",
|
| + RecordLongTimesHistogram("SoftwareReporter.RunningTime",
|
| registry_run_time);
|
| - UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName,
|
| - REPORTER_RUNNING_TIME_ERROR_NO_ERROR,
|
| - REPORTER_RUNNING_TIME_ERROR_MAX);
|
| + RecordEnumerationHistogram(kRunningTimeErrorMetricName,
|
| + REPORTER_RUNNING_TIME_ERROR_NO_ERROR,
|
| + REPORTER_RUNNING_TIME_ERROR_MAX);
|
| } else if (!has_start_time && !has_end_time) {
|
| - UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName,
|
| - REPORTER_RUNNING_TIME_ERROR_MISSING_BOTH_TIMES,
|
| - REPORTER_RUNNING_TIME_ERROR_MAX);
|
| + RecordEnumerationHistogram(kRunningTimeErrorMetricName,
|
| + REPORTER_RUNNING_TIME_ERROR_MISSING_BOTH_TIMES,
|
| + REPORTER_RUNNING_TIME_ERROR_MAX);
|
| } else if (!has_start_time) {
|
| - UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName,
|
| - REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME,
|
| - REPORTER_RUNNING_TIME_ERROR_MAX);
|
| + RecordEnumerationHistogram(kRunningTimeErrorMetricName,
|
| + REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME,
|
| + REPORTER_RUNNING_TIME_ERROR_MAX);
|
| } else {
|
| DCHECK(!has_end_time);
|
| - UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName,
|
| - REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME,
|
| - REPORTER_RUNNING_TIME_ERROR_MAX);
|
| + RecordEnumerationHistogram(kRunningTimeErrorMetricName,
|
| + REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME,
|
| + REPORTER_RUNNING_TIME_ERROR_MAX);
|
| }
|
| }
|
|
|
| // Report the UwS scan times of the software reporter tool via UMA.
|
| void ReportScanTimes() const {
|
| base::string16 scan_times_key_path = base::StringPrintf(
|
| - L"%ls\\%ls", kSoftwareRemovalToolRegistryKey, kScanTimesSubKey);
|
| + L"%ls\\%ls", registry_key_.c_str(), kScanTimesSubKey);
|
| base::win::RegKey scan_times_key(
|
| HKEY_CURRENT_USER, scan_times_key_path.c_str(), KEY_ALL_ACCESS);
|
| if (!scan_times_key.Valid())
|
| @@ -284,30 +296,104 @@ class UMAHistogramReporter {
|
| ERROR_SUCCESS) {
|
| base::TimeDelta scan_time =
|
| base::TimeDelta::FromInternalValue(raw_scan_time);
|
| - base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
|
| - kScanTimesMetricName,
|
| - base::HistogramBase::kUmaTargetedHistogramFlag);
|
| - if (histogram) {
|
| - // We report the number of seconds plus one because it can take less
|
| - // than one second to scan some UwS and the count passed to |AddCount|
|
| - // must be at least one.
|
| - histogram->AddCount(uws_id, scan_time.InSeconds() + 1);
|
| - }
|
| + // We report the number of seconds plus one because it can take less
|
| + // than one second to scan some UwS and the count passed to |AddCount|
|
| + // must be at least one.
|
| + RecordSparseHistogramCount(kScanTimesMetricName, uws_id,
|
| + scan_time.InSeconds() + 1);
|
| }
|
| }
|
| // Clean up by deleting the scan times key, which is a subkey of the main
|
| // reporter key.
|
| scan_times_key.Close();
|
| - base::win::RegKey reporter_key(HKEY_CURRENT_USER,
|
| - kSoftwareRemovalToolRegistryKey,
|
| + base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(),
|
| KEY_ENUMERATE_SUB_KEYS);
|
| if (reporter_key.Valid())
|
| reporter_key.DeleteKey(kScanTimesSubKey);
|
| }
|
| +
|
| + void RecordReporterStep(SwReporterUmaValue value) {
|
| + RecordEnumerationHistogram("SoftwareReporter.Step", value, SW_REPORTER_MAX);
|
| + }
|
| +
|
| + private:
|
| + std::string FullName(const std::string& name) const {
|
| + if (suffix_.empty())
|
| + return name;
|
| + return base::StringPrintf("%s_%s", name, suffix_);
|
| + }
|
| +
|
| + template <typename HistogramType, typename SampleType>
|
| + void RecordHistogram(const std::string& name, SampleType sample) const {
|
| + base::HistogramBase* histogram = HistogramType::FactoryGet(
|
| + FullName(name), base::HistogramBase::kUmaTargetedHistogramFlag);
|
| + if (histogram)
|
| + histogram->Add(sample);
|
| + }
|
| +
|
| + template <typename SampleType>
|
| + void RecordBooleanHistogram(const std::string& name,
|
| + SampleType sample) const {
|
| + RecordHistogram<base::BooleanHistogram, SampleType>(name, sample);
|
| + }
|
| +
|
| + template <typename SampleType>
|
| + void RecordEnumerationHistogram(const std::string& name,
|
| + SampleType sample,
|
| + SampleType boundary) const {
|
| + // See HISTOGRAM_ENUMERATION_WITH_FLAG.
|
| + base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
|
| + FullName(name), 1, boundary, boundary + 1,
|
| + base::HistogramBase::kUmaTargetedHistogramFlag);
|
| + if (histogram)
|
| + histogram->Add(sample);
|
| + }
|
| +
|
| + template <typename SampleType>
|
| + void RecordLongTimesHistogram(const std::string& name,
|
| + SampleType sample) const {
|
| + // See UMA_HISTOGRAM_LONG_TIMES.
|
| + base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
|
| + FullName(name), base::TimeDelta::FromMilliseconds(1),
|
| + base::TimeDelta::FromHours(1), 100,
|
| + base::HistogramBase::kUmaTargetedHistogramFlag);
|
| + if (histogram)
|
| + histogram->AddTime(sample);
|
| + }
|
| +
|
| + template <typename SampleType>
|
| + void RecordMemoryKBHistogram(const std::string& name,
|
| + SampleType sample) const {
|
| + // See UMA_HISTOGRAM_MEMORY_KB.
|
| + base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
|
| + FullName(name), 1000, 500000, 50,
|
| + base::HistogramBase::kUmaTargetedHistogramFlag);
|
| + if (histogram)
|
| + histogram->Add(sample);
|
| + }
|
| +
|
| + template <typename SampleType>
|
| + void RecordSparseHistogram(const std::string& name, SampleType sample) const {
|
| + RecordHistogram<base::SparseHistogram, SampleType>(name, sample);
|
| + }
|
| +
|
| + template <typename SampleType>
|
| + void RecordSparseHistogramCount(const std::string& name,
|
| + SampleType sample,
|
| + int count) const {
|
| + base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
|
| + FullName(name), base::HistogramBase::kUmaTargetedHistogramFlag);
|
| + if (histogram)
|
| + histogram->AddCount(sample, count);
|
| + }
|
| +
|
| + std::string suffix_;
|
| + std::wstring registry_key_;
|
| };
|
|
|
| void RecordReporterStepHistogram(SwReporterUmaValue value) {
|
| - UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX);
|
| + UMAHistogramReporter uma;
|
| + uma.RecordReporterStep(value);
|
| }
|
|
|
| void DisplaySRTPrompt(const base::FilePath& download_path) {
|
| @@ -371,12 +457,13 @@ int LaunchAndWaitForExit(const SwReporterInvocation& invocation) {
|
| // This exit code is used to identify that a reporter run didn't happen, so
|
| // the result should be ignored and a rerun scheduled for the usual delay.
|
| int exit_code = kReporterFailureExitCode;
|
| + UMAHistogramReporter uma(invocation.suffix);
|
| if (reporter_process.IsValid()) {
|
| - RecordReporterStepHistogram(SW_REPORTER_START_EXECUTION);
|
| + uma.RecordReporterStep(SW_REPORTER_START_EXECUTION);
|
| bool success = reporter_process.WaitForExit(&exit_code);
|
| DCHECK(success);
|
| } else {
|
| - RecordReporterStepHistogram(SW_REPORTER_FAILED_TO_START);
|
| + uma.RecordReporterStep(SW_REPORTER_FAILED_TO_START);
|
| }
|
| return exit_code;
|
| }
|
| @@ -512,7 +599,7 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| public:
|
| // Starts the sequence of attempts to run the reporter.
|
| static void Run(
|
| - const SwReporterInvocation& invocation,
|
| + const std::queue<SwReporterInvocation>& invocations,
|
| const base::Version& version,
|
| const scoped_refptr<base::TaskRunner>& main_thread_task_runner,
|
| const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
|
| @@ -521,11 +608,11 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| // 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_ == invocations &&
|
| + instance_->version_.IsValid() && instance_->version_ == version)
|
| return;
|
|
|
| - instance_->invocation_ = invocation;
|
| + instance_->invocations_ = invocations;
|
| instance_->version_ = version;
|
| instance_->main_thread_task_runner_ = main_thread_task_runner;
|
| instance_->blocking_task_runner_ = blocking_task_runner;
|
| @@ -536,6 +623,34 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| }
|
| }
|
|
|
| + // Launch the command line at the head of the queue.
|
| + void LaunchNextInvocation(
|
| + const std::queue<SwReporterInvocation>& invocations) {
|
| + DCHECK(!invocations.empty());
|
| + // Make a non-const copy of the queue so it can be manipulated.
|
| + auto remaining_invocations = invocations;
|
| + auto next_invocation = remaining_invocations.front();
|
| + remaining_invocations.pop();
|
| +
|
| + // 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,
|
| +
|
| + // 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,
|
| + remaining_invocations));
|
| + }
|
| +
|
| private:
|
| ReporterRunner() : first_run_(true) {}
|
| ~ReporterRunner() override {}
|
| @@ -553,9 +668,12 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| // This method is called on the UI thread when the reporter run has completed.
|
| // 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,
|
| - int exit_code) {
|
| + void ReporterDone(
|
| + const base::Time& reporter_start_time,
|
| + const base::Version& version,
|
| + const SwReporterInvocation& finished_invocation,
|
| + const std::queue<SwReporterInvocation>& remaining_invocations,
|
| + int exit_code) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| if (g_reporter_done_notifier_)
|
| @@ -573,12 +691,14 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| if (exit_code == kReporterFailureExitCode)
|
| return;
|
|
|
| - UMAHistogramReporter uma;
|
| + UMAHistogramReporter uma(finished_invocation.suffix);
|
| uma.ReportVersion(version);
|
| uma.ReportExitCode(exit_code);
|
| - uma.ReportFoundUwS();
|
| + uma.ReportFoundUwS(!finished_invocation.is_experimental /*use_rappor*/);
|
| +
|
| + // Only save results from the canonical version of the software.
|
| PrefService* local_state = g_browser_process->local_state();
|
| - if (local_state) {
|
| + if (local_state && !finished_invocation.is_experimental) {
|
| local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code);
|
| local_state->SetInt64(prefs::kSwReporterLastTimeTriggered,
|
| base::Time::Now().ToInternalValue());
|
| @@ -587,16 +707,26 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| uma.ReportScanTimes();
|
| uma.ReportMemoryUsage();
|
|
|
| + if (!remaining_invocations.empty()) {
|
| + // Only the experimental version should have multiple invocations.
|
| + DCHECK(finished_invocation.is_experimental);
|
| + LaunchNextInvocation(remaining_invocations);
|
| + }
|
| +
|
| + // Only continue to launch the prompt for the canonical version.
|
| + if (finished_invocation.is_experimental)
|
| + return;
|
| +
|
| if (!IsInSRTPromptFieldTrialGroups()) {
|
| // Knowing about disabled field trial is more important than reporter not
|
| // finding anything to remove, so check this case first.
|
| - RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL);
|
| + uma.RecordReporterStep(SW_REPORTER_NO_PROMPT_FIELD_TRIAL);
|
| return;
|
| }
|
|
|
| if (exit_code != kSwReporterPostRebootCleanupNeeded &&
|
| exit_code != kSwReporterCleanupNeeded) {
|
| - RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_NEEDED);
|
| + uma.RecordReporterStep(SW_REPORTER_NO_PROMPT_NEEDED);
|
| return;
|
| }
|
|
|
| @@ -608,7 +738,7 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| // decide when it's time to download the SRT and when to display the prompt.
|
| Browser* browser = chrome::FindLastActive();
|
| if (!browser) {
|
| - RecordReporterStepHistogram(SW_REPORTER_NO_BROWSER);
|
| + uma.RecordReporterStep(SW_REPORTER_NO_BROWSER);
|
| BrowserList::AddObserver(this);
|
| } else {
|
| MaybeFetchSRT(browser, version_);
|
| @@ -645,15 +775,8 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| if (g_launch_ready_notifier_)
|
| g_launch_ready_notifier_.Run();
|
|
|
| - // 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_));
|
| + if (!invocations_.empty())
|
| + LaunchNextInvocation(invocations_);
|
| } else {
|
| main_thread_task_runner_->PostDelayedTask(
|
| FROM_HERE,
|
| @@ -663,7 +786,7 @@ class ReporterRunner : public chrome::BrowserListObserver {
|
| }
|
|
|
| bool first_run_;
|
| - SwReporterInvocation invocation_;
|
| + std::queue<SwReporterInvocation> invocations_;
|
| base::Version version_;
|
| scoped_refptr<base::TaskRunner> main_thread_task_runner_;
|
| scoped_refptr<base::TaskRunner> blocking_task_runner_;
|
| @@ -684,24 +807,36 @@ ReporterRunner* ReporterRunner::instance_ = nullptr;
|
|
|
| } // namespace
|
|
|
| -SwReporterInvocation::SwReporterInvocation() : command_line(0, nullptr) {}
|
| +SwReporterInvocation::SwReporterInvocation()
|
| + : command_line(0, nullptr), is_experimental(false) {}
|
|
|
| SwReporterInvocation::SwReporterInvocation(const base::FilePath& exe_path)
|
| - : command_line(exe_path) {}
|
| + : command_line(exe_path), is_experimental(false) {}
|
|
|
| SwReporterInvocation::SwReporterInvocation(
|
| const base::CommandLine& command_line)
|
| - : command_line(command_line) {}
|
| + : command_line(command_line), is_experimental(false) {}
|
|
|
| bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const {
|
| - return command_line.argv() == other.command_line.argv();
|
| + return command_line.argv() == other.command_line.argv() &&
|
| + suffix == other.suffix && is_experimental == other.is_experimental;
|
| }
|
|
|
| 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, main_thread_task_runner,
|
| + std::queue<SwReporterInvocation> invocations;
|
| + invocations.push(invocation);
|
| + ReporterRunner::Run(invocations, version, main_thread_task_runner,
|
| + blocking_task_runner);
|
| +}
|
| +
|
| +void RunSwReporters(const std::queue<SwReporterInvocation>& invocations,
|
| + const base::Version& version,
|
| + scoped_refptr<base::TaskRunner> main_thread_task_runner,
|
| + scoped_refptr<base::TaskRunner> blocking_task_runner) {
|
| + ReporterRunner::Run(invocations, version, main_thread_task_runner,
|
| blocking_task_runner);
|
| }
|
|
|
|
|