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

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: Move regexps to local vars Created 4 years, 4 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
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 <memory>
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/bind.h" 12 #include "base/bind.h"
12 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
13 #include "base/callback_helpers.h" 14 #include "base/callback_helpers.h"
14 #include "base/command_line.h" 15 #include "base/command_line.h"
15 #include "base/files/file_path.h" 16 #include "base/files/file_path.h"
16 #include "base/macros.h" 17 #include "base/macros.h"
17 #include "base/metrics/field_trial.h" 18 #include "base/metrics/field_trial.h"
18 #include "base/metrics/histogram_macros.h" 19 #include "base/metrics/histogram_macros.h"
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 } 136 }
136 } 137 }
137 if (show_bubble) 138 if (show_bubble)
138 global_error->ShowBubbleView(browser); 139 global_error->ShowBubbleView(browser);
139 } 140 }
140 141
141 // This function is called from a worker thread to launch the SwReporter and 142 // This function is called from a worker thread to launch the SwReporter and
142 // wait for termination to collect its exit code. This task could be 143 // wait for termination to collect its exit code. This task could be
143 // interrupted by a shutdown at any time, so it shouldn't depend on anything 144 // interrupted by a shutdown at any time, so it shouldn't depend on anything
144 // external that could be shut down beforehand. 145 // external that could be shut down beforehand.
145 int LaunchAndWaitForExit(const base::FilePath& exe_path) { 146 int LaunchAndWaitForExit(const SwReporterInvocation& invocation) {
146 if (!g_reporter_launcher_.is_null()) 147 if (!g_reporter_launcher_.is_null())
147 return g_reporter_launcher_.Run(exe_path); 148 return g_reporter_launcher_.Run(invocation.command_line.GetProgram());
148 base::Process reporter_process = 149 base::Process reporter_process =
149 base::LaunchProcess(exe_path.value(), base::LaunchOptions()); 150 base::LaunchProcess(invocation.command_line, base::LaunchOptions());
150 // This exit code is used to identify that a reporter run didn't happen, so 151 // This exit code is used to identify that a reporter run didn't happen, so
151 // the result should be ignored and a rerun scheduled for the usual delay. 152 // the result should be ignored and a rerun scheduled for the usual delay.
152 int exit_code = kReporterFailureExitCode; 153 int exit_code = kReporterFailureExitCode;
153 if (reporter_process.IsValid()) { 154 if (reporter_process.IsValid()) {
154 RecordReporterStepHistogram(SW_REPORTER_START_EXECUTION); 155 RecordReporterStepHistogram(SW_REPORTER_START_EXECUTION,
156 invocation.suffix);
155 bool success = reporter_process.WaitForExit(&exit_code); 157 bool success = reporter_process.WaitForExit(&exit_code);
156 DCHECK(success); 158 DCHECK(success);
157 } else { 159 } else {
158 RecordReporterStepHistogram(SW_REPORTER_FAILED_TO_START); 160 RecordReporterStepHistogram(SW_REPORTER_FAILED_TO_START,
161 invocation.suffix);
159 } 162 }
160 return exit_code; 163 return exit_code;
161 } 164 }
162 165
166 std::string AddHistogramSuffix(const std::string& histogram,
167 const std::string& suffix) {
csharp 2016/08/11 18:58:02 Given the number of functions that have been modif
Joe Mason 2016/08/15 17:24:40 Done. Also I moved this refactor to http://crrev.c
168 if (suffix.empty())
169 return histogram;
170 return base::StringPrintf("%s_%s", histogram, suffix);
171 }
172
173 std::wstring RegistryKeyWithSuffix(const std::string& suffix) {
174 if (suffix.empty())
175 return kSoftwareRemovalToolRegistryKey;
176 return base::StringPrintf(L"%s\\%s", kSoftwareRemovalToolRegistryKey,
177 base::UTF8ToUTF16(suffix));
178 }
179
163 // Reports the software reporter tool's version via UMA. 180 // Reports the software reporter tool's version via UMA.
164 void ReportVersion(const base::Version& version) { 181 void ReportVersion(const base::Version& version, const std::string& suffix) {
165 DCHECK(!version.components().empty()); 182 DCHECK(!version.components().empty());
166 // The minor version is the 2nd last component of the version, 183 // The minor version is the 2nd last component of the version,
167 // or just the first component if there is only 1. 184 // or just the first component if there is only 1.
168 uint32_t minor_version = 0; 185 uint32_t minor_version = 0;
169 if (version.components().size() > 1) 186 if (version.components().size() > 1)
170 minor_version = version.components()[version.components().size() - 2]; 187 minor_version = version.components()[version.components().size() - 2];
171 else 188 else
172 minor_version = version.components()[0]; 189 minor_version = version.components()[0];
173 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MinorVersion", minor_version); 190 UMA_HISTOGRAM_SPARSE_SLOWLY(
191 AddHistogramSuffix("SoftwareReporter.MinorVersion", suffix),
192 minor_version);
174 193
175 // The major version for X.Y.Z is X*256^3+Y*256+Z. If there are additional 194 // The major version for X.Y.Z is X*256^3+Y*256+Z. If there are additional
176 // components, only the first three count, and if there are less than 3, the 195 // components, only the first three count, and if there are less than 3, the
177 // missing values are just replaced by zero. So 1 is equivalent 1.0.0. 196 // missing values are just replaced by zero. So 1 is equivalent 1.0.0.
178 DCHECK_LT(version.components()[0], 0x100U); 197 DCHECK_LT(version.components()[0], 0x100U);
179 uint32_t major_version = 0x1000000 * version.components()[0]; 198 uint32_t major_version = 0x1000000 * version.components()[0];
180 if (version.components().size() >= 2) { 199 if (version.components().size() >= 2) {
181 DCHECK_LT(version.components()[1], 0x10000U); 200 DCHECK_LT(version.components()[1], 0x10000U);
182 major_version += 0x100 * version.components()[1]; 201 major_version += 0x100 * version.components()[1];
183 } 202 }
184 if (version.components().size() >= 3) { 203 if (version.components().size() >= 3) {
185 DCHECK_LT(version.components()[2], 0x100U); 204 DCHECK_LT(version.components()[2], 0x100U);
186 major_version += version.components()[2]; 205 major_version += version.components()[2];
187 } 206 }
188 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MajorVersion", major_version); 207 UMA_HISTOGRAM_SPARSE_SLOWLY(
208 AddHistogramSuffix("SoftwareReporter.MajorVersion", suffix),
209 major_version);
189 } 210 }
190 211
191 // Reports UwS found by the software reporter tool via UMA and RAPPOR. 212 // Reports UwS found by the software reporter tool via UMA and RAPPOR.
192 void ReportFoundUwS() { 213 void ReportFoundUwS(const std::string& suffix) {
193 base::win::RegKey reporter_key(HKEY_CURRENT_USER, 214 base::win::RegKey reporter_key(HKEY_CURRENT_USER,
194 kSoftwareRemovalToolRegistryKey, 215 RegistryKeyWithSuffix(suffix).c_str(),
195 KEY_QUERY_VALUE | KEY_SET_VALUE); 216 KEY_QUERY_VALUE | KEY_SET_VALUE);
196 std::vector<base::string16> found_uws_strings; 217 std::vector<base::string16> found_uws_strings;
197 if (reporter_key.Valid() && 218 if (reporter_key.Valid() &&
198 reporter_key.ReadValues(kFoundUwsValueName, &found_uws_strings) == 219 reporter_key.ReadValues(kFoundUwsValueName, &found_uws_strings) ==
199 ERROR_SUCCESS) { 220 ERROR_SUCCESS) {
200 rappor::RapporService* rappor_service = g_browser_process->rappor_service(); 221 rappor::RapporService* rappor_service = g_browser_process->rappor_service();
201 222
202 bool parse_error = false; 223 bool parse_error = false;
203 for (const base::string16& uws_string : found_uws_strings) { 224 for (const base::string16& uws_string : found_uws_strings) {
204 // All UwS ids are expected to be integers. 225 // All UwS ids are expected to be integers.
205 uint32_t uws_id = 0; 226 uint32_t uws_id = 0;
206 if (base::StringToUint(uws_string, &uws_id)) { 227 if (base::StringToUint(uws_string, &uws_id)) {
207 UMA_HISTOGRAM_SPARSE_SLOWLY(kFoundUwsMetricName, uws_id); 228 UMA_HISTOGRAM_SPARSE_SLOWLY(AddHistogramSuffix(kFoundUwsMetricName,
229 suffix), uws_id);
208 if (rappor_service) { 230 if (rappor_service) {
209 rappor_service->RecordSample(kFoundUwsMetricName, 231 rappor_service->RecordSample(kFoundUwsMetricName,
210 rappor::COARSE_RAPPOR_TYPE, 232 rappor::COARSE_RAPPOR_TYPE,
211 base::UTF16ToUTF8(uws_string)); 233 base::UTF16ToUTF8(uws_string));
212 } 234 }
213 } else { 235 } else {
214 parse_error = true; 236 parse_error = true;
215 } 237 }
216 } 238 }
217 239
218 // Clean up the old value. 240 // Clean up the old value.
219 reporter_key.DeleteValue(kFoundUwsValueName); 241 reporter_key.DeleteValue(kFoundUwsValueName);
220 242
221 UMA_HISTOGRAM_BOOLEAN(kFoundUwsReadErrorMetricName, parse_error); 243 UMA_HISTOGRAM_BOOLEAN(AddHistogramSuffix(kFoundUwsReadErrorMetricName,
244 suffix), parse_error);
222 } 245 }
223 } 246 }
224 247
225 // Reports to UMA the memory usage of the software reporter tool as reported by 248 // Reports to UMA the memory usage of the software reporter tool as reported by
226 // the tool itself in the Windows registry. 249 // the tool itself in the Windows registry.
227 void ReportSwReporterMemoryUsage() { 250 void ReportSwReporterMemoryUsage(const std::string& suffix) {
228 base::win::RegKey reporter_key(HKEY_CURRENT_USER, 251 base::win::RegKey reporter_key(HKEY_CURRENT_USER,
229 kSoftwareRemovalToolRegistryKey, 252 RegistryKeyWithSuffix(suffix).c_str(),
230 KEY_QUERY_VALUE | KEY_SET_VALUE); 253 KEY_QUERY_VALUE | KEY_SET_VALUE);
231 DWORD memory_used = 0; 254 DWORD memory_used = 0;
232 if (reporter_key.Valid() && 255 if (reporter_key.Valid() &&
233 reporter_key.ReadValueDW(kMemoryUsedValueName, &memory_used) == 256 reporter_key.ReadValueDW(kMemoryUsedValueName, &memory_used) ==
234 ERROR_SUCCESS) { 257 ERROR_SUCCESS) {
235 UMA_HISTOGRAM_MEMORY_KB(kMemoryUsedMetricName, memory_used); 258 UMA_HISTOGRAM_MEMORY_KB(AddHistogramSuffix(kMemoryUsedMetricName, suffix),
259 memory_used);
236 reporter_key.DeleteValue(kMemoryUsedValueName); 260 reporter_key.DeleteValue(kMemoryUsedValueName);
237 } 261 }
238 } 262 }
239 263
240 } // namespace 264 } // namespace
241 265
242 // Class that will attempt to download the SRT, showing the SRT notification 266 // Class that will attempt to download the SRT, showing the SRT notification
243 // bubble when the download operation is complete. Instances of SRTFetcher own 267 // bubble when the download operation is complete. Instances of SRTFetcher own
244 // themselves, they will self-delete on completion of the network request when 268 // themselves, they will self-delete on completion of the network request when
245 // OnURLFetchComplete is called. 269 // OnURLFetchComplete is called.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 380
357 // Download the SRT. 381 // Download the SRT.
358 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START); 382 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START);
359 383
360 // All the work happens in the self-deleting class below. 384 // All the work happens in the self-deleting class below.
361 new SRTFetcher(profile); 385 new SRTFetcher(profile);
362 } 386 }
363 387
364 // Report the SwReporter run time with UMA both as reported by the tool via 388 // Report the SwReporter run time with UMA both as reported by the tool via
365 // the registry and as measured by |ReporterRunner|. 389 // the registry and as measured by |ReporterRunner|.
366 void ReportSwReporterRuntime(const base::TimeDelta& reporter_running_time) { 390 void ReportSwReporterRuntime(const base::TimeDelta& reporter_running_time,
367 UMA_HISTOGRAM_LONG_TIMES("SoftwareReporter.RunningTimeAccordingToChrome", 391 const std::string& suffix) {
368 reporter_running_time); 392 UMA_HISTOGRAM_LONG_TIMES(AddHistogramSuffix(
393 "SoftwareReporter.RunningTimeAccordingToChrome", suffix),
394 reporter_running_time);
369 395
370 base::win::RegKey reporter_key( 396 base::win::RegKey reporter_key(
371 HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_ALL_ACCESS); 397 HKEY_CURRENT_USER, RegistryKeyWithSuffix(suffix).c_str(), KEY_ALL_ACCESS);
372 if (!reporter_key.Valid()) { 398 if (!reporter_key.Valid()) {
373 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, 399 UMA_HISTOGRAM_ENUMERATION(
374 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID, 400 AddHistogramSuffix(kRunningTimeErrorMetricName, suffix),
375 REPORTER_RUNNING_TIME_ERROR_MAX); 401 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID,
402 REPORTER_RUNNING_TIME_ERROR_MAX);
376 return; 403 return;
377 } 404 }
378 405
379 bool has_start_time = false; 406 bool has_start_time = false;
380 int64_t start_time_value = 0; 407 int64_t start_time_value = 0;
381 if (reporter_key.HasValue(kStartTimeValueName) && 408 if (reporter_key.HasValue(kStartTimeValueName) &&
382 reporter_key.ReadInt64(kStartTimeValueName, &start_time_value) == 409 reporter_key.ReadInt64(kStartTimeValueName, &start_time_value) ==
383 ERROR_SUCCESS) { 410 ERROR_SUCCESS) {
384 has_start_time = true; 411 has_start_time = true;
385 reporter_key.DeleteValue(kStartTimeValueName); 412 reporter_key.DeleteValue(kStartTimeValueName);
386 } 413 }
387 414
388 bool has_end_time = false; 415 bool has_end_time = false;
389 int64_t end_time_value = 0; 416 int64_t end_time_value = 0;
390 if (reporter_key.HasValue(kEndTimeValueName) && 417 if (reporter_key.HasValue(kEndTimeValueName) &&
391 reporter_key.ReadInt64(kEndTimeValueName, &end_time_value) == 418 reporter_key.ReadInt64(kEndTimeValueName, &end_time_value) ==
392 ERROR_SUCCESS) { 419 ERROR_SUCCESS) {
393 has_end_time = true; 420 has_end_time = true;
394 reporter_key.DeleteValue(kEndTimeValueName); 421 reporter_key.DeleteValue(kEndTimeValueName);
395 } 422 }
396 423
397 if (has_start_time && has_end_time) { 424 if (has_start_time && has_end_time) {
398 base::TimeDelta registry_run_time = 425 base::TimeDelta registry_run_time =
399 base::Time::FromInternalValue(end_time_value) - 426 base::Time::FromInternalValue(end_time_value) -
400 base::Time::FromInternalValue(start_time_value); 427 base::Time::FromInternalValue(start_time_value);
401 UMA_HISTOGRAM_LONG_TIMES("SoftwareReporter.RunningTime", registry_run_time); 428 UMA_HISTOGRAM_LONG_TIMES(AddHistogramSuffix("SoftwareReporter.RunningTime",
402 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, 429 suffix), registry_run_time);
403 REPORTER_RUNNING_TIME_ERROR_NO_ERROR, 430 UMA_HISTOGRAM_ENUMERATION(
404 REPORTER_RUNNING_TIME_ERROR_MAX); 431 AddHistogramSuffix(kRunningTimeErrorMetricName, suffix),
432 REPORTER_RUNNING_TIME_ERROR_NO_ERROR,
433 REPORTER_RUNNING_TIME_ERROR_MAX);
405 } else if (!has_start_time && !has_end_time) { 434 } else if (!has_start_time && !has_end_time) {
406 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, 435 UMA_HISTOGRAM_ENUMERATION(
407 REPORTER_RUNNING_TIME_ERROR_MISSING_BOTH_TIMES, 436 AddHistogramSuffix(kRunningTimeErrorMetricName, suffix),
408 REPORTER_RUNNING_TIME_ERROR_MAX); 437 REPORTER_RUNNING_TIME_ERROR_MISSING_BOTH_TIMES,
438 REPORTER_RUNNING_TIME_ERROR_MAX);
409 } else if (!has_start_time) { 439 } else if (!has_start_time) {
410 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, 440 UMA_HISTOGRAM_ENUMERATION(
411 REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME, 441 AddHistogramSuffix(kRunningTimeErrorMetricName, suffix),
412 REPORTER_RUNNING_TIME_ERROR_MAX); 442 REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME,
443 REPORTER_RUNNING_TIME_ERROR_MAX);
413 } else { 444 } else {
414 DCHECK(!has_end_time); 445 DCHECK(!has_end_time);
415 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, 446 UMA_HISTOGRAM_ENUMERATION(
416 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME, 447 AddHistogramSuffix(kRunningTimeErrorMetricName, suffix),
417 REPORTER_RUNNING_TIME_ERROR_MAX); 448 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME,
449 REPORTER_RUNNING_TIME_ERROR_MAX);
418 } 450 }
419 } 451 }
420 452
421 // Report the UwS scan times of the software reporter tool via UMA. 453 // Report the UwS scan times of the software reporter tool via UMA.
422 void ReportSwReporterScanTimes() { 454 void ReportSwReporterScanTimes(const std::string& suffix) {
423 base::string16 scan_times_key_path = base::StringPrintf( 455 base::string16 scan_times_key_path = base::StringPrintf(
424 L"%ls\\%ls", kSoftwareRemovalToolRegistryKey, kScanTimesSubKey); 456 L"%ls\\%ls", RegistryKeyWithSuffix(suffix).c_str(), kScanTimesSubKey);
425 base::win::RegKey scan_times_key(HKEY_CURRENT_USER, 457 base::win::RegKey scan_times_key(HKEY_CURRENT_USER,
426 scan_times_key_path.c_str(), KEY_ALL_ACCESS); 458 scan_times_key_path.c_str(), KEY_ALL_ACCESS);
427 if (!scan_times_key.Valid()) 459 if (!scan_times_key.Valid())
428 return; 460 return;
429 461
430 base::string16 value_name; 462 base::string16 value_name;
431 int uws_id = 0; 463 int uws_id = 0;
432 int64_t raw_scan_time = 0; 464 int64_t raw_scan_time = 0;
433 int num_scan_times = scan_times_key.GetValueCount(); 465 int num_scan_times = scan_times_key.GetValueCount();
434 for (int i = 0; i < num_scan_times; ++i) { 466 for (int i = 0; i < num_scan_times; ++i) {
435 if (scan_times_key.GetValueNameAt(i, &value_name) == ERROR_SUCCESS && 467 if (scan_times_key.GetValueNameAt(i, &value_name) == ERROR_SUCCESS &&
436 base::StringToInt(value_name, &uws_id) && 468 base::StringToInt(value_name, &uws_id) &&
437 scan_times_key.ReadInt64(value_name.c_str(), &raw_scan_time) == 469 scan_times_key.ReadInt64(value_name.c_str(), &raw_scan_time) ==
438 ERROR_SUCCESS) { 470 ERROR_SUCCESS) {
439 base::TimeDelta scan_time = 471 base::TimeDelta scan_time =
440 base::TimeDelta::FromInternalValue(raw_scan_time); 472 base::TimeDelta::FromInternalValue(raw_scan_time);
441 base::HistogramBase* histogram = base::SparseHistogram::FactoryGet( 473 base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
442 kScanTimesMetricName, base::HistogramBase::kUmaTargetedHistogramFlag); 474 AddHistogramSuffix(kScanTimesMetricName, suffix),
475 base::HistogramBase::kUmaTargetedHistogramFlag);
443 if (histogram) { 476 if (histogram) {
444 // We report the number of seconds plus one because it can take less 477 // We report the number of seconds plus one because it can take less
445 // than one second to scan some UwS and the count passed to |AddCount| 478 // than one second to scan some UwS and the count passed to |AddCount|
446 // must be at least one. 479 // must be at least one.
447 histogram->AddCount(uws_id, scan_time.InSeconds() + 1); 480 histogram->AddCount(uws_id, scan_time.InSeconds() + 1);
448 } 481 }
449 } 482 }
450 } 483 }
451 // Clean up by deleting the scan times key, which is a subkey of the main 484 // Clean up by deleting the scan times key, which is a subkey of the main
452 // reporter key. 485 // reporter key.
453 scan_times_key.Close(); 486 scan_times_key.Close();
454 base::win::RegKey reporter_key(HKEY_CURRENT_USER, 487 base::win::RegKey reporter_key(HKEY_CURRENT_USER,
455 kSoftwareRemovalToolRegistryKey, 488 RegistryKeyWithSuffix(suffix).c_str(),
456 KEY_ENUMERATE_SUB_KEYS); 489 KEY_ENUMERATE_SUB_KEYS);
457 if (reporter_key.Valid()) 490 if (reporter_key.Valid())
458 reporter_key.DeleteKey(kScanTimesSubKey); 491 reporter_key.DeleteKey(kScanTimesSubKey);
459 } 492 }
460 493
461 // This class tries to run the reporter and reacts to its exit code. It 494 // This class tries to run the reporter and reacts to its exit code. It
462 // schedules subsequent runs as needed, or retries as soon as a browser is 495 // schedules subsequent runs as needed, or retries as soon as a browser is
463 // available when none is on first try. 496 // available when none is on first try.
464 class ReporterRunner : public chrome::BrowserListObserver { 497 class ReporterRunner : public chrome::BrowserListObserver {
465 public: 498 public:
466 // Starts the sequence of attempts to run the reporter. 499 // Starts the sequence of attempts to run the reporter.
467 static void Run( 500 static void Run(
468 const base::FilePath& exe_path, 501 const std::vector<SwReporterInvocation>& invocation_queue,
469 const base::Version& version, 502 const base::Version& version,
470 const scoped_refptr<base::TaskRunner>& main_thread_task_runner, 503 const scoped_refptr<base::TaskRunner>& main_thread_task_runner,
471 const scoped_refptr<base::TaskRunner>& blocking_task_runner) { 504 const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
472 if (!instance_) 505 if (!instance_)
473 instance_ = new ReporterRunner; 506 instance_ = new ReporterRunner;
474 DCHECK_CURRENTLY_ON(BrowserThread::UI); 507 DCHECK_CURRENTLY_ON(BrowserThread::UI);
475 // There's nothing to do if the path and version of the reporter has not 508 // There's nothing to do if the path and version of the reporter has not
476 // changed, we just keep running the tasks that are running now. 509 // changed, we just keep running the tasks that are running now.
477 if (instance_->exe_path_ == exe_path && instance_->version_.IsValid() && 510 if (instance_->invocation_queue_ == invocation_queue &&
511 instance_->version_.IsValid() &&
478 instance_->version_ == version) 512 instance_->version_ == version)
479 return; 513 return;
480 bool first_run = instance_->exe_path_.empty(); 514 bool first_run = instance_->invocation_queue_.empty();
481 515
482 instance_->exe_path_ = exe_path; 516 instance_->invocation_queue_ = invocation_queue;
483 instance_->version_ = version; 517 instance_->version_ = version;
484 instance_->main_thread_task_runner_ = main_thread_task_runner; 518 instance_->main_thread_task_runner_ = main_thread_task_runner;
485 instance_->blocking_task_runner_ = blocking_task_runner; 519 instance_->blocking_task_runner_ = blocking_task_runner;
486 520
487 if (first_run) 521 if (first_run)
488 instance_->TryToRun(); 522 instance_->TryToRun();
489 } 523 }
490 524
525 // Launch the command line at the head of the queue.
526 void LaunchNextInvocation(
527 const std::vector<SwReporterInvocation>& invocation_queue) {
528 DCHECK(!invocation_queue.empty());
529 auto head = invocation_queue.begin();
530 std::vector<SwReporterInvocation> tail(
531 head + 1, invocation_queue.end());
532
533 base::PostTaskAndReplyWithResult(
534 blocking_task_runner_.get(), FROM_HERE,
535
536 // Send the head of the queue to the launch callback.
537 base::Bind(&LaunchAndWaitForExit, *head),
538
539 // Send the tail of the queue to the next callback, which will handle the
540 // results of the first launch and then recursively launch everything in
541 // the tail.
542 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this),
543 base::Time::Now(), version_, head->suffix, tail));
544 }
545
491 private: 546 private:
492 ReporterRunner() {} 547 ReporterRunner() {}
493 ~ReporterRunner() override {} 548 ~ReporterRunner() override {}
494 549
495 // BrowserListObserver. 550 // BrowserListObserver.
496 void OnBrowserSetLastActive(Browser* browser) override {} 551 void OnBrowserSetLastActive(Browser* browser) override {}
497 void OnBrowserRemoved(Browser* browser) override {} 552 void OnBrowserRemoved(Browser* browser) override {}
498 void OnBrowserAdded(Browser* browser) override { 553 void OnBrowserAdded(Browser* browser) override {
499 DCHECK_CURRENTLY_ON(BrowserThread::UI); 554 DCHECK_CURRENTLY_ON(BrowserThread::UI);
500 DCHECK(browser); 555 DCHECK(browser);
501 MaybeFetchSRT(browser, version_); 556 MaybeFetchSRT(browser, version_);
502 BrowserList::RemoveObserver(this); 557 BrowserList::RemoveObserver(this);
503 } 558 }
504 559
505 // This method is called on the UI thread when the reporter run has completed. 560 // This method is called on the UI thread when the reporter run has completed.
506 // This is run as a task posted from an interruptible worker thread so should 561 // This is run as a task posted from an interruptible worker thread so should
507 // be resilient to unexpected shutdown. 562 // be resilient to unexpected shutdown.
508 void ReporterDone(const base::Time& reporter_start_time, 563 void ReporterDone(const base::Time& reporter_start_time,
509 const base::Version& version, 564 const base::Version& version,
510 int exit_code) { 565 const std::string& suffix,
566 const std::vector<SwReporterInvocation>& remaining_invocations,
567 int exit_code) {
511 DCHECK_CURRENTLY_ON(BrowserThread::UI); 568 DCHECK_CURRENTLY_ON(BrowserThread::UI);
512 569
570 bool is_experimental_version = !suffix.empty();
571
513 base::TimeDelta reporter_running_time = 572 base::TimeDelta reporter_running_time =
514 base::Time::Now() - reporter_start_time; 573 base::Time::Now() - reporter_start_time;
515 // Don't continue when the reporter process failed to launch, but still try 574 // Don't continue when the reporter process failed to launch, but still try
516 // again after the regular delay. It's not worth retrying earlier, risking 575 // again after the regular delay. It's not worth retrying earlier, risking
517 // running too often if it always fails, since not many users fail here. 576 // running too often if it always fails, since not many users fail here.
518 main_thread_task_runner_->PostDelayedTask( 577 main_thread_task_runner_->PostDelayedTask(
519 FROM_HERE, 578 FROM_HERE,
520 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), 579 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)),
521 base::TimeDelta::FromDays(days_between_reporter_runs_)); 580 base::TimeDelta::FromDays(days_between_reporter_runs_));
522 if (exit_code == kReporterFailureExitCode) 581 if (exit_code == kReporterFailureExitCode)
523 return; 582 return;
524 583
525 ReportVersion(version); 584 ReportVersion(version, suffix);
526 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code); 585 UMA_HISTOGRAM_SPARSE_SLOWLY(AddHistogramSuffix("SoftwareReporter.ExitCode",
527 ReportFoundUwS(); 586 suffix), exit_code);
587 ReportFoundUwS(suffix);
588
589 // Only save results from the canonical version of the software.
528 PrefService* local_state = g_browser_process->local_state(); 590 PrefService* local_state = g_browser_process->local_state();
529 if (local_state) { 591 if (local_state && !is_experimental_version) {
530 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code); 592 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code);
531 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered, 593 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered,
532 base::Time::Now().ToInternalValue()); 594 base::Time::Now().ToInternalValue());
533 } 595 }
534 ReportSwReporterRuntime(reporter_running_time); 596
535 ReportSwReporterScanTimes(); 597 ReportSwReporterRuntime(reporter_running_time, suffix);
536 ReportSwReporterMemoryUsage(); 598 ReportSwReporterScanTimes(suffix);
599 ReportSwReporterMemoryUsage(suffix);
600
601 if (!remaining_invocations.empty()) {
602 // Only the experimental version should have multiple invocations.
603 DCHECK(is_experimental_version);
604 LaunchNextInvocation(remaining_invocations);
605 }
606
607 // Only continue to launch the prompt for the canonical version.
608 if (is_experimental_version)
609 return;
537 610
538 if (!IsInSRTPromptFieldTrialGroups()) { 611 if (!IsInSRTPromptFieldTrialGroups()) {
539 // Knowing about disabled field trial is more important than reporter not 612 // Knowing about disabled field trial is more important than reporter not
540 // finding anything to remove, so check this case first. 613 // finding anything to remove, so check this case first.
541 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL); 614 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL);
542 return; 615 return;
543 } 616 }
544 617
545 if (exit_code != kSwReporterPostRebootCleanupNeeded && 618 if (exit_code != kSwReporterPostRebootCleanupNeeded &&
546 exit_code != kSwReporterCleanupNeeded) { 619 exit_code != kSwReporterCleanupNeeded) {
(...skipping 13 matching lines...) Expand all
560 BrowserList::AddObserver(this); 633 BrowserList::AddObserver(this);
561 } else { 634 } else {
562 MaybeFetchSRT(browser, version_); 635 MaybeFetchSRT(browser, version_);
563 } 636 }
564 } 637 }
565 638
566 void TryToRun() { 639 void TryToRun() {
567 DCHECK_CURRENTLY_ON(BrowserThread::UI); 640 DCHECK_CURRENTLY_ON(BrowserThread::UI);
568 PrefService* local_state = g_browser_process->local_state(); 641 PrefService* local_state = g_browser_process->local_state();
569 if (!version_.IsValid() || !local_state) { 642 if (!version_.IsValid() || !local_state) {
570 DCHECK(exe_path_.empty()); 643 DCHECK(invocation_queue_.empty());
571 return; 644 return;
572 } 645 }
573 646
574 // Run the reporter if it hasn't been triggered in the last 647 // Run the reporter if it hasn't been triggered in the last
575 // |days_between_reporter_runs_| days, which depends if there is a pending 648 // |days_between_reporter_runs_| days, which depends if there is a pending
576 // prompt to be added to Chrome's menu. 649 // prompt to be added to Chrome's menu.
577 if (local_state->GetBoolean(prefs::kSwReporterPendingPrompt)) { 650 if (local_state->GetBoolean(prefs::kSwReporterPendingPrompt)) {
578 days_between_reporter_runs_ = kDaysBetweenSwReporterRunsForPendingPrompt; 651 days_between_reporter_runs_ = kDaysBetweenSwReporterRunsForPendingPrompt;
579 RecordReporterStepHistogram(SW_REPORTER_RAN_DAILY); 652 RecordReporterStepHistogram(SW_REPORTER_RAN_DAILY);
580 } else { 653 } else {
581 days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; 654 days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns;
582 } 655 }
583 const base::Time last_time_triggered = base::Time::FromInternalValue( 656 const base::Time last_time_triggered = base::Time::FromInternalValue(
584 local_state->GetInt64(prefs::kSwReporterLastTimeTriggered)); 657 local_state->GetInt64(prefs::kSwReporterLastTimeTriggered));
585 base::TimeDelta next_trigger_delay( 658 base::TimeDelta next_trigger_delay(
586 last_time_triggered + 659 last_time_triggered +
587 base::TimeDelta::FromDays(days_between_reporter_runs_) - 660 base::TimeDelta::FromDays(days_between_reporter_runs_) -
588 base::Time::Now()); 661 base::Time::Now());
589 if (next_trigger_delay.ToInternalValue() <= 0 || 662 if (next_trigger_delay.ToInternalValue() <= 0 ||
590 // Also make sure the kSwReporterLastTimeTriggered value is not set in 663 // Also make sure the kSwReporterLastTimeTriggered value is not set in
591 // the future. 664 // the future.
592 last_time_triggered > base::Time::Now()) { 665 last_time_triggered > base::Time::Now()) {
593 // It's OK to simply |PostTaskAndReplyWithResult| so that 666 // It's OK to simply |PostTaskAndReplyWithResult| so that
grt (UTC plus 2) 2016/08/10 06:47:01 update comment
Joe Mason 2016/08/15 17:24:39 Done.
594 // |LaunchAndWaitForExit| doesn't need to access 667 // |LaunchAndWaitForExit| doesn't need to access
595 // |main_thread_task_runner_| since the callback is not delayed and the 668 // |main_thread_task_runner_| since the callback is not delayed and the
596 // test task runner won't need to force it. 669 // test task runner won't need to force it.
597 base::PostTaskAndReplyWithResult( 670 if (!invocation_queue_.empty())
598 blocking_task_runner_.get(), FROM_HERE, 671 LaunchNextInvocation(invocation_queue_);
599 base::Bind(&LaunchAndWaitForExit, exe_path_),
600 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this),
601 base::Time::Now(), version_));
602 } else { 672 } else {
603 main_thread_task_runner_->PostDelayedTask( 673 main_thread_task_runner_->PostDelayedTask(
604 FROM_HERE, 674 FROM_HERE,
605 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), 675 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)),
606 next_trigger_delay); 676 next_trigger_delay);
607 } 677 }
608 } 678 }
609 679
610 base::FilePath exe_path_; 680 std::vector<SwReporterInvocation> invocation_queue_;
611 base::Version version_; 681 base::Version version_;
612 scoped_refptr<base::TaskRunner> main_thread_task_runner_; 682 scoped_refptr<base::TaskRunner> main_thread_task_runner_;
613 scoped_refptr<base::TaskRunner> blocking_task_runner_; 683 scoped_refptr<base::TaskRunner> blocking_task_runner_;
614 684
615 // This value is used to identify how long to wait before starting a new run 685 // This value is used to identify how long to wait before starting a new run
616 // of the reporter. It's initialized with the default value and may be changed 686 // of the reporter. It's initialized with the default value and may be changed
617 // to a different value when a prompt is pending and the reporter should be 687 // to a different value when a prompt is pending and the reporter should be
618 // run before adding the global error to the Chrome menu. 688 // run before adding the global error to the Chrome menu.
619 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; 689 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns;
620 690
621 // A single leaky instance. 691 // A single leaky instance.
622 static ReporterRunner* instance_; 692 static ReporterRunner* instance_;
623 693
624 DISALLOW_COPY_AND_ASSIGN(ReporterRunner); 694 DISALLOW_COPY_AND_ASSIGN(ReporterRunner);
625 }; 695 };
626 696
627 ReporterRunner* ReporterRunner::instance_ = nullptr; 697 ReporterRunner* ReporterRunner::instance_ = nullptr;
628 698
629 } // namespace 699 } // namespace
630 700
701 SwReporterInvocation::SwReporterInvocation()
702 : command_line(0, nullptr) {
703 }
704
705 SwReporterInvocation::SwReporterInvocation(const base::FilePath& exe_path)
706 : command_line(exe_path) {
707 }
708
709 SwReporterInvocation::SwReporterInvocation(
710 const base::CommandLine& command_line, const std::string& suffix)
711 : command_line(command_line), suffix(suffix) {
712 }
713
714 bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const {
715 return command_line.argv() == other.command_line.argv() &&
716 suffix == other.suffix;
717 }
718
631 void RunSwReporter( 719 void RunSwReporter(
632 const base::FilePath& exe_path, 720 const base::FilePath& exe_path,
633 const base::Version& version, 721 const base::Version& version,
634 const scoped_refptr<base::TaskRunner>& main_thread_task_runner, 722 const scoped_refptr<base::TaskRunner>& main_thread_task_runner,
635 const scoped_refptr<base::TaskRunner>& blocking_task_runner) { 723 const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
636 ReporterRunner::Run(exe_path, version, main_thread_task_runner, 724 std::vector<SwReporterInvocation> invocations =
725 {SwReporterInvocation(exe_path)};
726 ReporterRunner::Run(invocations, version, main_thread_task_runner,
637 blocking_task_runner); 727 blocking_task_runner);
638 } 728 }
639 729
730 void RunExperimentalSwReporters(
731 const std::vector<SwReporterInvocation>& invocation_queue,
732 const base::Version& version,
733 const scoped_refptr<base::TaskRunner>& main_thread_task_runner,
734 const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
735 ReporterRunner::Run(invocation_queue, version, main_thread_task_runner,
736 blocking_task_runner);
737 }
738
640 bool ReporterFoundUws() { 739 bool ReporterFoundUws() {
641 PrefService* local_state = g_browser_process->local_state(); 740 PrefService* local_state = g_browser_process->local_state();
642 if (!local_state) 741 if (!local_state)
643 return false; 742 return false;
644 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode); 743 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode);
645 return exit_code == kSwReporterCleanupNeeded; 744 return exit_code == kSwReporterCleanupNeeded;
646 } 745 }
647 746
648 bool UserHasRunCleaner() { 747 bool UserHasRunCleaner() {
649 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey); 748 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey);
650 cleaner_key_path.append(L"\\").append(kCleanerSubKey); 749 cleaner_key_path.append(L"\\").append(kCleanerSubKey);
651 750
652 base::win::RegKey srt_cleaner_key(HKEY_CURRENT_USER, cleaner_key_path.c_str(), 751 base::win::RegKey srt_cleaner_key(HKEY_CURRENT_USER, cleaner_key_path.c_str(),
653 KEY_QUERY_VALUE); 752 KEY_QUERY_VALUE);
654 753
655 return srt_cleaner_key.Valid() && srt_cleaner_key.GetValueCount() > 0; 754 return srt_cleaner_key.Valid() && srt_cleaner_key.GetValueCount() > 0;
656 } 755 }
657 756
658 void SetReporterLauncherForTesting(const ReporterLauncher& reporter_launcher) { 757 void SetReporterLauncherForTesting(const ReporterLauncher& reporter_launcher) {
659 g_reporter_launcher_ = reporter_launcher; 758 g_reporter_launcher_ = reporter_launcher;
660 } 759 }
661 760
662 void SetPromptTriggerForTesting(const PromptTrigger& prompt_trigger) { 761 void SetPromptTriggerForTesting(const PromptTrigger& prompt_trigger) {
663 g_prompt_trigger_ = prompt_trigger; 762 g_prompt_trigger_ = prompt_trigger;
664 } 763 }
665 764
666 } // namespace safe_browsing 765 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698