OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h" | 5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
| 10 #include <queue> |
10 #include <vector> | 11 #include <vector> |
11 | 12 |
12 #include "base/bind.h" | 13 #include "base/bind.h" |
13 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
14 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
15 #include "base/command_line.h" | 16 #include "base/command_line.h" |
16 #include "base/files/file_path.h" | 17 #include "base/files/file_path.h" |
17 #include "base/macros.h" | 18 #include "base/macros.h" |
18 #include "base/metrics/field_trial.h" | 19 #include "base/metrics/field_trial.h" |
19 #include "base/metrics/histogram_macros.h" | 20 #include "base/metrics/histogram.h" |
20 #include "base/metrics/sparse_histogram.h" | 21 #include "base/metrics/sparse_histogram.h" |
21 #include "base/process/launch.h" | 22 #include "base/process/launch.h" |
22 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
23 #include "base/strings/stringprintf.h" | 24 #include "base/strings/stringprintf.h" |
24 #include "base/strings/utf_string_conversions.h" | 25 #include "base/strings/utf_string_conversions.h" |
25 #include "base/task_runner_util.h" | 26 #include "base/task_runner_util.h" |
26 #include "base/time/time.h" | 27 #include "base/time/time.h" |
27 #include "base/win/registry.h" | 28 #include "base/win/registry.h" |
28 #include "chrome/browser/browser_process.h" | 29 #include "chrome/browser/browser_process.h" |
29 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" | 30 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 const wchar_t kFoundUwsValueName[] = L"FoundUws"; | 114 const wchar_t kFoundUwsValueName[] = L"FoundUws"; |
114 const wchar_t kMemoryUsedValueName[] = L"MemoryUsed"; | 115 const wchar_t kMemoryUsedValueName[] = L"MemoryUsed"; |
115 | 116 |
116 const char kFoundUwsMetricName[] = "SoftwareReporter.FoundUwS"; | 117 const char kFoundUwsMetricName[] = "SoftwareReporter.FoundUwS"; |
117 const char kFoundUwsReadErrorMetricName[] = | 118 const char kFoundUwsReadErrorMetricName[] = |
118 "SoftwareReporter.FoundUwSReadError"; | 119 "SoftwareReporter.FoundUwSReadError"; |
119 const char kScanTimesMetricName[] = "SoftwareReporter.UwSScanTimes"; | 120 const char kScanTimesMetricName[] = "SoftwareReporter.UwSScanTimes"; |
120 const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed"; | 121 const char kMemoryUsedMetricName[] = "SoftwareReporter.MemoryUsed"; |
121 | 122 |
122 // Reports metrics about the software reporter via UMA (and sometimes Rappor). | 123 // Reports metrics about the software reporter via UMA (and sometimes Rappor). |
| 124 // |
| 125 // This will format the names of the histograms at runtime by adding an |
| 126 // optional suffix, so the UMA_HISTOGRAM macros won't work. Use RecordHistogram |
| 127 // and related helper methods instead. |
123 class UMAHistogramReporter { | 128 class UMAHistogramReporter { |
124 public: | 129 public: |
| 130 UMAHistogramReporter(const std::string& suffix = std::string()) |
| 131 : suffix_(suffix), |
| 132 registry_key_(suffix.empty() |
| 133 ? kSoftwareRemovalToolRegistryKey |
| 134 : base::StringPrintf(L"%s\\%s", |
| 135 kSoftwareRemovalToolRegistryKey, |
| 136 base::UTF8ToUTF16(suffix))) {} |
| 137 |
125 // Reports the software reporter tool's version via UMA. | 138 // Reports the software reporter tool's version via UMA. |
126 void ReportVersion(const base::Version& version) const { | 139 void ReportVersion(const base::Version& version) const { |
127 DCHECK(!version.components().empty()); | 140 DCHECK(!version.components().empty()); |
128 // The minor version is the 2nd last component of the version, | 141 // The minor version is the 2nd last component of the version, |
129 // or just the first component if there is only 1. | 142 // or just the first component if there is only 1. |
130 uint32_t minor_version = 0; | 143 uint32_t minor_version = 0; |
131 if (version.components().size() > 1) | 144 if (version.components().size() > 1) |
132 minor_version = version.components()[version.components().size() - 2]; | 145 minor_version = version.components()[version.components().size() - 2]; |
133 else | 146 else |
134 minor_version = version.components()[0]; | 147 minor_version = version.components()[0]; |
135 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MinorVersion", minor_version); | 148 RecordSparseHistogram("SoftwareReporter.MinorVersion", minor_version); |
136 | 149 |
137 // The major version for X.Y.Z is X*256^3+Y*256+Z. If there are additional | 150 // The major version for X.Y.Z is X*256^3+Y*256+Z. If there are additional |
138 // components, only the first three count, and if there are less than 3, the | 151 // components, only the first three count, and if there are less than 3, the |
139 // missing values are just replaced by zero. So 1 is equivalent 1.0.0. | 152 // missing values are just replaced by zero. So 1 is equivalent 1.0.0. |
140 DCHECK_LT(version.components()[0], 0x100U); | 153 DCHECK_LT(version.components()[0], 0x100U); |
141 uint32_t major_version = 0x1000000 * version.components()[0]; | 154 uint32_t major_version = 0x1000000 * version.components()[0]; |
142 if (version.components().size() >= 2) { | 155 if (version.components().size() >= 2) { |
143 DCHECK_LT(version.components()[1], 0x10000U); | 156 DCHECK_LT(version.components()[1], 0x10000U); |
144 major_version += 0x100 * version.components()[1]; | 157 major_version += 0x100 * version.components()[1]; |
145 } | 158 } |
146 if (version.components().size() >= 3) { | 159 if (version.components().size() >= 3) { |
147 DCHECK_LT(version.components()[2], 0x100U); | 160 DCHECK_LT(version.components()[2], 0x100U); |
148 major_version += version.components()[2]; | 161 major_version += version.components()[2]; |
149 } | 162 } |
150 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MajorVersion", major_version); | 163 RecordSparseHistogram("SoftwareReporter.MajorVersion", major_version); |
151 } | 164 } |
152 | 165 |
153 void ReportExitCode(int exit_code) const { | 166 void ReportExitCode(int exit_code) const { |
154 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code); | 167 RecordSparseHistogram("SoftwareReporter.ExitCode", exit_code); |
155 } | 168 } |
156 | 169 |
157 // Reports UwS found by the software reporter tool via UMA and RAPPOR. | 170 // Reports UwS found by the software reporter tool via UMA and RAPPOR. |
158 void ReportFoundUwS() const { | 171 void ReportFoundUwS(bool use_rappor) const { |
159 base::win::RegKey reporter_key(HKEY_CURRENT_USER, | 172 base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(), |
160 kSoftwareRemovalToolRegistryKey, | |
161 KEY_QUERY_VALUE | KEY_SET_VALUE); | 173 KEY_QUERY_VALUE | KEY_SET_VALUE); |
162 std::vector<base::string16> found_uws_strings; | 174 std::vector<base::string16> found_uws_strings; |
163 if (reporter_key.Valid() && | 175 if (reporter_key.Valid() && |
164 reporter_key.ReadValues(kFoundUwsValueName, &found_uws_strings) == | 176 reporter_key.ReadValues(kFoundUwsValueName, &found_uws_strings) == |
165 ERROR_SUCCESS) { | 177 ERROR_SUCCESS) { |
166 rappor::RapporService* rappor_service = | 178 rappor::RapporService* rappor_service = nullptr; |
167 g_browser_process->rappor_service(); | 179 if (use_rappor) |
| 180 rappor_service = g_browser_process->rappor_service(); |
168 | 181 |
169 bool parse_error = false; | 182 bool parse_error = false; |
170 for (const base::string16& uws_string : found_uws_strings) { | 183 for (const base::string16& uws_string : found_uws_strings) { |
171 // All UwS ids are expected to be integers. | 184 // All UwS ids are expected to be integers. |
172 uint32_t uws_id = 0; | 185 uint32_t uws_id = 0; |
173 if (base::StringToUint(uws_string, &uws_id)) { | 186 if (base::StringToUint(uws_string, &uws_id)) { |
174 UMA_HISTOGRAM_SPARSE_SLOWLY(kFoundUwsMetricName, uws_id); | 187 RecordSparseHistogram(kFoundUwsMetricName, uws_id); |
175 if (rappor_service) { | 188 if (rappor_service) { |
176 rappor_service->RecordSample(kFoundUwsMetricName, | 189 rappor_service->RecordSample(kFoundUwsMetricName, |
177 rappor::COARSE_RAPPOR_TYPE, | 190 rappor::COARSE_RAPPOR_TYPE, |
178 base::UTF16ToUTF8(uws_string)); | 191 base::UTF16ToUTF8(uws_string)); |
179 } | 192 } |
180 } else { | 193 } else { |
181 parse_error = true; | 194 parse_error = true; |
182 } | 195 } |
183 } | 196 } |
184 | 197 |
185 // Clean up the old value. | 198 // Clean up the old value. |
186 reporter_key.DeleteValue(kFoundUwsValueName); | 199 reporter_key.DeleteValue(kFoundUwsValueName); |
187 | 200 |
188 UMA_HISTOGRAM_BOOLEAN(kFoundUwsReadErrorMetricName, parse_error); | 201 RecordBooleanHistogram(kFoundUwsReadErrorMetricName, parse_error); |
189 } | 202 } |
190 } | 203 } |
191 | 204 |
192 // Reports to UMA the memory usage of the software reporter tool as reported | 205 // Reports to UMA the memory usage of the software reporter tool as reported |
193 // by | 206 // by |
194 // the tool itself in the Windows registry. | 207 // the tool itself in the Windows registry. |
195 void ReportMemoryUsage() const { | 208 void ReportMemoryUsage() const { |
196 base::win::RegKey reporter_key(HKEY_CURRENT_USER, | 209 base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(), |
197 kSoftwareRemovalToolRegistryKey, | |
198 KEY_QUERY_VALUE | KEY_SET_VALUE); | 210 KEY_QUERY_VALUE | KEY_SET_VALUE); |
199 DWORD memory_used = 0; | 211 DWORD memory_used = 0; |
200 if (reporter_key.Valid() && | 212 if (reporter_key.Valid() && |
201 reporter_key.ReadValueDW(kMemoryUsedValueName, &memory_used) == | 213 reporter_key.ReadValueDW(kMemoryUsedValueName, &memory_used) == |
202 ERROR_SUCCESS) { | 214 ERROR_SUCCESS) { |
203 UMA_HISTOGRAM_MEMORY_KB(kMemoryUsedMetricName, memory_used); | 215 RecordMemoryKBHistogram(kMemoryUsedMetricName, memory_used); |
204 reporter_key.DeleteValue(kMemoryUsedValueName); | 216 reporter_key.DeleteValue(kMemoryUsedValueName); |
205 } | 217 } |
206 } | 218 } |
207 | 219 |
208 // Report the SwReporter run time with UMA both as reported by the tool via | 220 // Report the SwReporter run time with UMA both as reported by the tool via |
209 // the registry and as measured by |ReporterRunner|. | 221 // the registry and as measured by |ReporterRunner|. |
210 void ReportRuntime(const base::TimeDelta& reporter_running_time) const { | 222 void ReportRuntime(const base::TimeDelta& reporter_running_time) const { |
211 UMA_HISTOGRAM_LONG_TIMES("SoftwareReporter.RunningTimeAccordingToChrome", | 223 RecordLongTimesHistogram("SoftwareReporter.RunningTimeAccordingToChrome", |
212 reporter_running_time); | 224 reporter_running_time); |
213 | 225 |
214 base::win::RegKey reporter_key( | 226 base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(), |
215 HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_ALL_ACCESS); | 227 KEY_ALL_ACCESS); |
216 if (!reporter_key.Valid()) { | 228 if (!reporter_key.Valid()) { |
217 UMA_HISTOGRAM_ENUMERATION( | 229 RecordEnumerationHistogram( |
218 kRunningTimeErrorMetricName, | 230 kRunningTimeErrorMetricName, |
219 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID, | 231 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID, |
220 REPORTER_RUNNING_TIME_ERROR_MAX); | 232 REPORTER_RUNNING_TIME_ERROR_MAX); |
221 return; | 233 return; |
222 } | 234 } |
223 | 235 |
224 bool has_start_time = false; | 236 bool has_start_time = false; |
225 int64_t start_time_value = 0; | 237 int64_t start_time_value = 0; |
226 if (reporter_key.HasValue(kStartTimeValueName) && | 238 if (reporter_key.HasValue(kStartTimeValueName) && |
227 reporter_key.ReadInt64(kStartTimeValueName, &start_time_value) == | 239 reporter_key.ReadInt64(kStartTimeValueName, &start_time_value) == |
228 ERROR_SUCCESS) { | 240 ERROR_SUCCESS) { |
229 has_start_time = true; | 241 has_start_time = true; |
230 reporter_key.DeleteValue(kStartTimeValueName); | 242 reporter_key.DeleteValue(kStartTimeValueName); |
231 } | 243 } |
232 | 244 |
233 bool has_end_time = false; | 245 bool has_end_time = false; |
234 int64_t end_time_value = 0; | 246 int64_t end_time_value = 0; |
235 if (reporter_key.HasValue(kEndTimeValueName) && | 247 if (reporter_key.HasValue(kEndTimeValueName) && |
236 reporter_key.ReadInt64(kEndTimeValueName, &end_time_value) == | 248 reporter_key.ReadInt64(kEndTimeValueName, &end_time_value) == |
237 ERROR_SUCCESS) { | 249 ERROR_SUCCESS) { |
238 has_end_time = true; | 250 has_end_time = true; |
239 reporter_key.DeleteValue(kEndTimeValueName); | 251 reporter_key.DeleteValue(kEndTimeValueName); |
240 } | 252 } |
241 | 253 |
242 if (has_start_time && has_end_time) { | 254 if (has_start_time && has_end_time) { |
243 base::TimeDelta registry_run_time = | 255 base::TimeDelta registry_run_time = |
244 base::Time::FromInternalValue(end_time_value) - | 256 base::Time::FromInternalValue(end_time_value) - |
245 base::Time::FromInternalValue(start_time_value); | 257 base::Time::FromInternalValue(start_time_value); |
246 UMA_HISTOGRAM_LONG_TIMES("SoftwareReporter.RunningTime", | 258 RecordLongTimesHistogram("SoftwareReporter.RunningTime", |
247 registry_run_time); | 259 registry_run_time); |
248 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, | 260 RecordEnumerationHistogram(kRunningTimeErrorMetricName, |
249 REPORTER_RUNNING_TIME_ERROR_NO_ERROR, | 261 REPORTER_RUNNING_TIME_ERROR_NO_ERROR, |
250 REPORTER_RUNNING_TIME_ERROR_MAX); | 262 REPORTER_RUNNING_TIME_ERROR_MAX); |
251 } else if (!has_start_time && !has_end_time) { | 263 } else if (!has_start_time && !has_end_time) { |
252 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, | 264 RecordEnumerationHistogram(kRunningTimeErrorMetricName, |
253 REPORTER_RUNNING_TIME_ERROR_MISSING_BOTH_TIMES, | 265 REPORTER_RUNNING_TIME_ERROR_MISSING_BOTH_TIMES, |
254 REPORTER_RUNNING_TIME_ERROR_MAX); | 266 REPORTER_RUNNING_TIME_ERROR_MAX); |
255 } else if (!has_start_time) { | 267 } else if (!has_start_time) { |
256 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, | 268 RecordEnumerationHistogram(kRunningTimeErrorMetricName, |
257 REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME, | 269 REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME, |
258 REPORTER_RUNNING_TIME_ERROR_MAX); | 270 REPORTER_RUNNING_TIME_ERROR_MAX); |
259 } else { | 271 } else { |
260 DCHECK(!has_end_time); | 272 DCHECK(!has_end_time); |
261 UMA_HISTOGRAM_ENUMERATION(kRunningTimeErrorMetricName, | 273 RecordEnumerationHistogram(kRunningTimeErrorMetricName, |
262 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME, | 274 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME, |
263 REPORTER_RUNNING_TIME_ERROR_MAX); | 275 REPORTER_RUNNING_TIME_ERROR_MAX); |
264 } | 276 } |
265 } | 277 } |
266 | 278 |
267 // Report the UwS scan times of the software reporter tool via UMA. | 279 // Report the UwS scan times of the software reporter tool via UMA. |
268 void ReportScanTimes() const { | 280 void ReportScanTimes() const { |
269 base::string16 scan_times_key_path = base::StringPrintf( | 281 base::string16 scan_times_key_path = base::StringPrintf( |
270 L"%ls\\%ls", kSoftwareRemovalToolRegistryKey, kScanTimesSubKey); | 282 L"%ls\\%ls", registry_key_.c_str(), kScanTimesSubKey); |
271 base::win::RegKey scan_times_key( | 283 base::win::RegKey scan_times_key( |
272 HKEY_CURRENT_USER, scan_times_key_path.c_str(), KEY_ALL_ACCESS); | 284 HKEY_CURRENT_USER, scan_times_key_path.c_str(), KEY_ALL_ACCESS); |
273 if (!scan_times_key.Valid()) | 285 if (!scan_times_key.Valid()) |
274 return; | 286 return; |
275 | 287 |
276 base::string16 value_name; | 288 base::string16 value_name; |
277 int uws_id = 0; | 289 int uws_id = 0; |
278 int64_t raw_scan_time = 0; | 290 int64_t raw_scan_time = 0; |
279 int num_scan_times = scan_times_key.GetValueCount(); | 291 int num_scan_times = scan_times_key.GetValueCount(); |
280 for (int i = 0; i < num_scan_times; ++i) { | 292 for (int i = 0; i < num_scan_times; ++i) { |
281 if (scan_times_key.GetValueNameAt(i, &value_name) == ERROR_SUCCESS && | 293 if (scan_times_key.GetValueNameAt(i, &value_name) == ERROR_SUCCESS && |
282 base::StringToInt(value_name, &uws_id) && | 294 base::StringToInt(value_name, &uws_id) && |
283 scan_times_key.ReadInt64(value_name.c_str(), &raw_scan_time) == | 295 scan_times_key.ReadInt64(value_name.c_str(), &raw_scan_time) == |
284 ERROR_SUCCESS) { | 296 ERROR_SUCCESS) { |
285 base::TimeDelta scan_time = | 297 base::TimeDelta scan_time = |
286 base::TimeDelta::FromInternalValue(raw_scan_time); | 298 base::TimeDelta::FromInternalValue(raw_scan_time); |
287 base::HistogramBase* histogram = base::SparseHistogram::FactoryGet( | 299 // We report the number of seconds plus one because it can take less |
288 kScanTimesMetricName, | 300 // than one second to scan some UwS and the count passed to |AddCount| |
289 base::HistogramBase::kUmaTargetedHistogramFlag); | 301 // must be at least one. |
290 if (histogram) { | 302 RecordSparseHistogramCount(kScanTimesMetricName, uws_id, |
291 // We report the number of seconds plus one because it can take less | 303 scan_time.InSeconds() + 1); |
292 // than one second to scan some UwS and the count passed to |AddCount| | |
293 // must be at least one. | |
294 histogram->AddCount(uws_id, scan_time.InSeconds() + 1); | |
295 } | |
296 } | 304 } |
297 } | 305 } |
298 // Clean up by deleting the scan times key, which is a subkey of the main | 306 // Clean up by deleting the scan times key, which is a subkey of the main |
299 // reporter key. | 307 // reporter key. |
300 scan_times_key.Close(); | 308 scan_times_key.Close(); |
301 base::win::RegKey reporter_key(HKEY_CURRENT_USER, | 309 base::win::RegKey reporter_key(HKEY_CURRENT_USER, registry_key_.c_str(), |
302 kSoftwareRemovalToolRegistryKey, | |
303 KEY_ENUMERATE_SUB_KEYS); | 310 KEY_ENUMERATE_SUB_KEYS); |
304 if (reporter_key.Valid()) | 311 if (reporter_key.Valid()) |
305 reporter_key.DeleteKey(kScanTimesSubKey); | 312 reporter_key.DeleteKey(kScanTimesSubKey); |
306 } | 313 } |
| 314 |
| 315 void RecordReporterStep(SwReporterUmaValue value) { |
| 316 RecordEnumerationHistogram("SoftwareReporter.Step", value, SW_REPORTER_MAX); |
| 317 } |
| 318 |
| 319 private: |
| 320 std::string FullName(const std::string& name) const { |
| 321 if (suffix_.empty()) |
| 322 return name; |
| 323 return base::StringPrintf("%s_%s", name, suffix_); |
| 324 } |
| 325 |
| 326 template <typename HistogramType, typename SampleType> |
| 327 void RecordHistogram(const std::string& name, SampleType sample) const { |
| 328 base::HistogramBase* histogram = HistogramType::FactoryGet( |
| 329 FullName(name), base::HistogramBase::kUmaTargetedHistogramFlag); |
| 330 if (histogram) |
| 331 histogram->Add(sample); |
| 332 } |
| 333 |
| 334 template <typename SampleType> |
| 335 void RecordBooleanHistogram(const std::string& name, |
| 336 SampleType sample) const { |
| 337 RecordHistogram<base::BooleanHistogram, SampleType>(name, sample); |
| 338 } |
| 339 |
| 340 template <typename SampleType> |
| 341 void RecordEnumerationHistogram(const std::string& name, |
| 342 SampleType sample, |
| 343 SampleType boundary) const { |
| 344 // See HISTOGRAM_ENUMERATION_WITH_FLAG. |
| 345 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( |
| 346 FullName(name), 1, boundary, boundary + 1, |
| 347 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 348 if (histogram) |
| 349 histogram->Add(sample); |
| 350 } |
| 351 |
| 352 template <typename SampleType> |
| 353 void RecordLongTimesHistogram(const std::string& name, |
| 354 SampleType sample) const { |
| 355 // See UMA_HISTOGRAM_LONG_TIMES. |
| 356 base::HistogramBase* histogram = base::Histogram::FactoryTimeGet( |
| 357 FullName(name), base::TimeDelta::FromMilliseconds(1), |
| 358 base::TimeDelta::FromHours(1), 100, |
| 359 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 360 if (histogram) |
| 361 histogram->AddTime(sample); |
| 362 } |
| 363 |
| 364 template <typename SampleType> |
| 365 void RecordMemoryKBHistogram(const std::string& name, |
| 366 SampleType sample) const { |
| 367 // See UMA_HISTOGRAM_MEMORY_KB. |
| 368 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( |
| 369 FullName(name), 1000, 500000, 50, |
| 370 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 371 if (histogram) |
| 372 histogram->Add(sample); |
| 373 } |
| 374 |
| 375 template <typename SampleType> |
| 376 void RecordSparseHistogram(const std::string& name, SampleType sample) const { |
| 377 RecordHistogram<base::SparseHistogram, SampleType>(name, sample); |
| 378 } |
| 379 |
| 380 template <typename SampleType> |
| 381 void RecordSparseHistogramCount(const std::string& name, |
| 382 SampleType sample, |
| 383 int count) const { |
| 384 base::HistogramBase* histogram = base::SparseHistogram::FactoryGet( |
| 385 FullName(name), base::HistogramBase::kUmaTargetedHistogramFlag); |
| 386 if (histogram) |
| 387 histogram->AddCount(sample, count); |
| 388 } |
| 389 |
| 390 std::string suffix_; |
| 391 std::wstring registry_key_; |
307 }; | 392 }; |
308 | 393 |
309 void RecordReporterStepHistogram(SwReporterUmaValue value) { | 394 void RecordReporterStepHistogram(SwReporterUmaValue value) { |
310 UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX); | 395 UMAHistogramReporter uma; |
| 396 uma.RecordReporterStep(value); |
311 } | 397 } |
312 | 398 |
313 void DisplaySRTPrompt(const base::FilePath& download_path) { | 399 void DisplaySRTPrompt(const base::FilePath& download_path) { |
314 // Find the last active browser, which may be NULL, in which case we won't | 400 // Find the last active browser, which may be NULL, in which case we won't |
315 // show the prompt this time and will wait until the next run of the | 401 // show the prompt this time and will wait until the next run of the |
316 // reporter. We can't use other ways of finding a browser because we don't | 402 // reporter. We can't use other ways of finding a browser because we don't |
317 // have a profile. | 403 // have a profile. |
318 Browser* browser = chrome::FindLastActive(); | 404 Browser* browser = chrome::FindLastActive(); |
319 if (!browser) | 405 if (!browser) |
320 return; | 406 return; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 // interrupted by a shutdown at any time, so it shouldn't depend on anything | 450 // interrupted by a shutdown at any time, so it shouldn't depend on anything |
365 // external that could be shut down beforehand. | 451 // external that could be shut down beforehand. |
366 int LaunchAndWaitForExit(const SwReporterInvocation& invocation) { | 452 int LaunchAndWaitForExit(const SwReporterInvocation& invocation) { |
367 if (!g_reporter_launcher_.is_null()) | 453 if (!g_reporter_launcher_.is_null()) |
368 return g_reporter_launcher_.Run(invocation); | 454 return g_reporter_launcher_.Run(invocation); |
369 base::Process reporter_process = | 455 base::Process reporter_process = |
370 base::LaunchProcess(invocation.command_line, base::LaunchOptions()); | 456 base::LaunchProcess(invocation.command_line, base::LaunchOptions()); |
371 // This exit code is used to identify that a reporter run didn't happen, so | 457 // This exit code is used to identify that a reporter run didn't happen, so |
372 // the result should be ignored and a rerun scheduled for the usual delay. | 458 // the result should be ignored and a rerun scheduled for the usual delay. |
373 int exit_code = kReporterFailureExitCode; | 459 int exit_code = kReporterFailureExitCode; |
| 460 UMAHistogramReporter uma(invocation.suffix); |
374 if (reporter_process.IsValid()) { | 461 if (reporter_process.IsValid()) { |
375 RecordReporterStepHistogram(SW_REPORTER_START_EXECUTION); | 462 uma.RecordReporterStep(SW_REPORTER_START_EXECUTION); |
376 bool success = reporter_process.WaitForExit(&exit_code); | 463 bool success = reporter_process.WaitForExit(&exit_code); |
377 DCHECK(success); | 464 DCHECK(success); |
378 } else { | 465 } else { |
379 RecordReporterStepHistogram(SW_REPORTER_FAILED_TO_START); | 466 uma.RecordReporterStep(SW_REPORTER_FAILED_TO_START); |
380 } | 467 } |
381 return exit_code; | 468 return exit_code; |
382 } | 469 } |
383 | 470 |
384 } // namespace | 471 } // namespace |
385 | 472 |
386 // Class that will attempt to download the SRT, showing the SRT notification | 473 // Class that will attempt to download the SRT, showing the SRT notification |
387 // bubble when the download operation is complete. Instances of SRTFetcher own | 474 // bubble when the download operation is complete. Instances of SRTFetcher own |
388 // themselves, they will self-delete on completion of the network request when | 475 // themselves, they will self-delete on completion of the network request when |
389 // OnURLFetchComplete is called. | 476 // OnURLFetchComplete is called. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 new SRTFetcher(profile); | 592 new SRTFetcher(profile); |
506 } | 593 } |
507 | 594 |
508 // This class tries to run the reporter and reacts to its exit code. It | 595 // This class tries to run the reporter and reacts to its exit code. It |
509 // schedules subsequent runs as needed, or retries as soon as a browser is | 596 // schedules subsequent runs as needed, or retries as soon as a browser is |
510 // available when none is on first try. | 597 // available when none is on first try. |
511 class ReporterRunner : public chrome::BrowserListObserver { | 598 class ReporterRunner : public chrome::BrowserListObserver { |
512 public: | 599 public: |
513 // Starts the sequence of attempts to run the reporter. | 600 // Starts the sequence of attempts to run the reporter. |
514 static void Run( | 601 static void Run( |
515 const SwReporterInvocation& invocation, | 602 const std::queue<SwReporterInvocation>& invocations, |
516 const base::Version& version, | 603 const base::Version& version, |
517 const scoped_refptr<base::TaskRunner>& main_thread_task_runner, | 604 const scoped_refptr<base::TaskRunner>& main_thread_task_runner, |
518 const scoped_refptr<base::TaskRunner>& blocking_task_runner) { | 605 const scoped_refptr<base::TaskRunner>& blocking_task_runner) { |
519 if (!instance_) | 606 if (!instance_) |
520 instance_ = new ReporterRunner; | 607 instance_ = new ReporterRunner; |
521 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 608 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
522 // There's nothing to do if the path and version of the reporter has not | 609 // There's nothing to do if the path and version of the reporter has not |
523 // changed, we just keep running the tasks that are running now. | 610 // changed, we just keep running the tasks that are running now. |
524 if (instance_->invocation_ == invocation && instance_->version_.IsValid() && | 611 if (instance_->invocations_ == invocations && |
525 instance_->version_ == version) | 612 instance_->version_.IsValid() && instance_->version_ == version) |
526 return; | 613 return; |
527 | 614 |
528 instance_->invocation_ = invocation; | 615 instance_->invocations_ = invocations; |
529 instance_->version_ = version; | 616 instance_->version_ = version; |
530 instance_->main_thread_task_runner_ = main_thread_task_runner; | 617 instance_->main_thread_task_runner_ = main_thread_task_runner; |
531 instance_->blocking_task_runner_ = blocking_task_runner; | 618 instance_->blocking_task_runner_ = blocking_task_runner; |
532 | 619 |
533 if (instance_->first_run_) { | 620 if (instance_->first_run_) { |
534 instance_->first_run_ = false; | 621 instance_->first_run_ = false; |
535 instance_->TryToRun(); | 622 instance_->TryToRun(); |
536 } | 623 } |
537 } | 624 } |
538 | 625 |
| 626 // Launch the command line at the head of the queue. |
| 627 void LaunchNextInvocation( |
| 628 const std::queue<SwReporterInvocation>& invocations) { |
| 629 DCHECK(!invocations.empty()); |
| 630 // Make a non-const copy of the queue so it can be manipulated. |
| 631 auto remaining_invocations = invocations; |
| 632 auto next_invocation = remaining_invocations.front(); |
| 633 remaining_invocations.pop(); |
| 634 |
| 635 // It's OK to simply |PostTaskAndReplyWithResult| so that |
| 636 // |LaunchAndWaitForExit| doesn't need to access |main_thread_task_runner_| |
| 637 // since the callback is not delayed and the test task runner won't need to |
| 638 // force it. |
| 639 base::PostTaskAndReplyWithResult( |
| 640 blocking_task_runner_.get(), FROM_HERE, |
| 641 |
| 642 // Send the head of the queue to the launch callback. |
| 643 base::Bind(&LaunchAndWaitForExit, next_invocation), |
| 644 |
| 645 // Send the tail of the queue to the next callback, which will handle |
| 646 // the |
| 647 // results of the first launch and then recursively launch everything in |
| 648 // the tail. |
| 649 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), |
| 650 base::Time::Now(), version_, next_invocation, |
| 651 remaining_invocations)); |
| 652 } |
| 653 |
539 private: | 654 private: |
540 ReporterRunner() : first_run_(true) {} | 655 ReporterRunner() : first_run_(true) {} |
541 ~ReporterRunner() override {} | 656 ~ReporterRunner() override {} |
542 | 657 |
543 // BrowserListObserver. | 658 // BrowserListObserver. |
544 void OnBrowserSetLastActive(Browser* browser) override {} | 659 void OnBrowserSetLastActive(Browser* browser) override {} |
545 void OnBrowserRemoved(Browser* browser) override {} | 660 void OnBrowserRemoved(Browser* browser) override {} |
546 void OnBrowserAdded(Browser* browser) override { | 661 void OnBrowserAdded(Browser* browser) override { |
547 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 662 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
548 DCHECK(browser); | 663 DCHECK(browser); |
549 MaybeFetchSRT(browser, version_); | 664 MaybeFetchSRT(browser, version_); |
550 BrowserList::RemoveObserver(this); | 665 BrowserList::RemoveObserver(this); |
551 } | 666 } |
552 | 667 |
553 // This method is called on the UI thread when the reporter run has completed. | 668 // This method is called on the UI thread when the reporter run has completed. |
554 // This is run as a task posted from an interruptible worker thread so should | 669 // This is run as a task posted from an interruptible worker thread so should |
555 // be resilient to unexpected shutdown. | 670 // be resilient to unexpected shutdown. |
556 void ReporterDone(const base::Time& reporter_start_time, | 671 void ReporterDone( |
557 const base::Version& version, | 672 const base::Time& reporter_start_time, |
558 int exit_code) { | 673 const base::Version& version, |
| 674 const SwReporterInvocation& finished_invocation, |
| 675 const std::queue<SwReporterInvocation>& remaining_invocations, |
| 676 int exit_code) { |
559 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 677 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
560 | 678 |
561 if (g_reporter_done_notifier_) | 679 if (g_reporter_done_notifier_) |
562 g_reporter_done_notifier_.Run(); | 680 g_reporter_done_notifier_.Run(); |
563 | 681 |
564 base::TimeDelta reporter_running_time = | 682 base::TimeDelta reporter_running_time = |
565 base::Time::Now() - reporter_start_time; | 683 base::Time::Now() - reporter_start_time; |
566 // Don't continue when the reporter process failed to launch, but still try | 684 // Don't continue when the reporter process failed to launch, but still try |
567 // again after the regular delay. It's not worth retrying earlier, risking | 685 // again after the regular delay. It's not worth retrying earlier, risking |
568 // running too often if it always fails, since not many users fail here. | 686 // running too often if it always fails, since not many users fail here. |
569 main_thread_task_runner_->PostDelayedTask( | 687 main_thread_task_runner_->PostDelayedTask( |
570 FROM_HERE, | 688 FROM_HERE, |
571 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), | 689 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), |
572 base::TimeDelta::FromDays(days_between_reporter_runs_)); | 690 base::TimeDelta::FromDays(days_between_reporter_runs_)); |
573 if (exit_code == kReporterFailureExitCode) | 691 if (exit_code == kReporterFailureExitCode) |
574 return; | 692 return; |
575 | 693 |
576 UMAHistogramReporter uma; | 694 UMAHistogramReporter uma(finished_invocation.suffix); |
577 uma.ReportVersion(version); | 695 uma.ReportVersion(version); |
578 uma.ReportExitCode(exit_code); | 696 uma.ReportExitCode(exit_code); |
579 uma.ReportFoundUwS(); | 697 uma.ReportFoundUwS(!finished_invocation.is_experimental /*use_rappor*/); |
| 698 |
| 699 // Only save results from the canonical version of the software. |
580 PrefService* local_state = g_browser_process->local_state(); | 700 PrefService* local_state = g_browser_process->local_state(); |
581 if (local_state) { | 701 if (local_state && !finished_invocation.is_experimental) { |
582 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code); | 702 local_state->SetInteger(prefs::kSwReporterLastExitCode, exit_code); |
583 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered, | 703 local_state->SetInt64(prefs::kSwReporterLastTimeTriggered, |
584 base::Time::Now().ToInternalValue()); | 704 base::Time::Now().ToInternalValue()); |
585 } | 705 } |
586 uma.ReportRuntime(reporter_running_time); | 706 uma.ReportRuntime(reporter_running_time); |
587 uma.ReportScanTimes(); | 707 uma.ReportScanTimes(); |
588 uma.ReportMemoryUsage(); | 708 uma.ReportMemoryUsage(); |
589 | 709 |
| 710 if (!remaining_invocations.empty()) { |
| 711 // Only the experimental version should have multiple invocations. |
| 712 DCHECK(finished_invocation.is_experimental); |
| 713 LaunchNextInvocation(remaining_invocations); |
| 714 } |
| 715 |
| 716 // Only continue to launch the prompt for the canonical version. |
| 717 if (finished_invocation.is_experimental) |
| 718 return; |
| 719 |
590 if (!IsInSRTPromptFieldTrialGroups()) { | 720 if (!IsInSRTPromptFieldTrialGroups()) { |
591 // Knowing about disabled field trial is more important than reporter not | 721 // Knowing about disabled field trial is more important than reporter not |
592 // finding anything to remove, so check this case first. | 722 // finding anything to remove, so check this case first. |
593 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_FIELD_TRIAL); | 723 uma.RecordReporterStep(SW_REPORTER_NO_PROMPT_FIELD_TRIAL); |
594 return; | 724 return; |
595 } | 725 } |
596 | 726 |
597 if (exit_code != kSwReporterPostRebootCleanupNeeded && | 727 if (exit_code != kSwReporterPostRebootCleanupNeeded && |
598 exit_code != kSwReporterCleanupNeeded) { | 728 exit_code != kSwReporterCleanupNeeded) { |
599 RecordReporterStepHistogram(SW_REPORTER_NO_PROMPT_NEEDED); | 729 uma.RecordReporterStep(SW_REPORTER_NO_PROMPT_NEEDED); |
600 return; | 730 return; |
601 } | 731 } |
602 | 732 |
603 // Find the last active browser, which may be NULL, in which case we need | 733 // Find the last active browser, which may be NULL, in which case we need |
604 // to wait for one to be available. We can't use other ways of finding a | 734 // to wait for one to be available. We can't use other ways of finding a |
605 // browser because we don't have a profile. And we need a browser to get to | 735 // browser because we don't have a profile. And we need a browser to get to |
606 // a profile, which we need, to tell whether we should prompt or not. | 736 // a profile, which we need, to tell whether we should prompt or not. |
607 // TODO(mad): crbug.com/503269, investigate whether we should change how we | 737 // TODO(mad): crbug.com/503269, investigate whether we should change how we |
608 // decide when it's time to download the SRT and when to display the prompt. | 738 // decide when it's time to download the SRT and when to display the prompt. |
609 Browser* browser = chrome::FindLastActive(); | 739 Browser* browser = chrome::FindLastActive(); |
610 if (!browser) { | 740 if (!browser) { |
611 RecordReporterStepHistogram(SW_REPORTER_NO_BROWSER); | 741 uma.RecordReporterStep(SW_REPORTER_NO_BROWSER); |
612 BrowserList::AddObserver(this); | 742 BrowserList::AddObserver(this); |
613 } else { | 743 } else { |
614 MaybeFetchSRT(browser, version_); | 744 MaybeFetchSRT(browser, version_); |
615 } | 745 } |
616 } | 746 } |
617 | 747 |
618 void TryToRun() { | 748 void TryToRun() { |
619 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 749 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
620 PrefService* local_state = g_browser_process->local_state(); | 750 PrefService* local_state = g_browser_process->local_state(); |
621 if (!version_.IsValid() || !local_state) { | 751 if (!version_.IsValid() || !local_state) { |
(...skipping 16 matching lines...) Expand all Loading... |
638 last_time_triggered + | 768 last_time_triggered + |
639 base::TimeDelta::FromDays(days_between_reporter_runs_) - | 769 base::TimeDelta::FromDays(days_between_reporter_runs_) - |
640 base::Time::Now()); | 770 base::Time::Now()); |
641 if (next_trigger_delay.ToInternalValue() <= 0 || | 771 if (next_trigger_delay.ToInternalValue() <= 0 || |
642 // Also make sure the kSwReporterLastTimeTriggered value is not set in | 772 // Also make sure the kSwReporterLastTimeTriggered value is not set in |
643 // the future. | 773 // the future. |
644 last_time_triggered > base::Time::Now()) { | 774 last_time_triggered > base::Time::Now()) { |
645 if (g_launch_ready_notifier_) | 775 if (g_launch_ready_notifier_) |
646 g_launch_ready_notifier_.Run(); | 776 g_launch_ready_notifier_.Run(); |
647 | 777 |
648 // It's OK to simply |PostTaskAndReplyWithResult| so that | 778 if (!invocations_.empty()) |
649 // |LaunchAndWaitForExit| doesn't need to access | 779 LaunchNextInvocation(invocations_); |
650 // |main_thread_task_runner_| since the callback is not delayed and the | |
651 // test task runner won't need to force it. | |
652 base::PostTaskAndReplyWithResult( | |
653 blocking_task_runner_.get(), FROM_HERE, | |
654 base::Bind(&LaunchAndWaitForExit, invocation_), | |
655 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), | |
656 base::Time::Now(), version_)); | |
657 } else { | 780 } else { |
658 main_thread_task_runner_->PostDelayedTask( | 781 main_thread_task_runner_->PostDelayedTask( |
659 FROM_HERE, | 782 FROM_HERE, |
660 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), | 783 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), |
661 next_trigger_delay); | 784 next_trigger_delay); |
662 } | 785 } |
663 } | 786 } |
664 | 787 |
665 bool first_run_; | 788 bool first_run_; |
666 SwReporterInvocation invocation_; | 789 std::queue<SwReporterInvocation> invocations_; |
667 base::Version version_; | 790 base::Version version_; |
668 scoped_refptr<base::TaskRunner> main_thread_task_runner_; | 791 scoped_refptr<base::TaskRunner> main_thread_task_runner_; |
669 scoped_refptr<base::TaskRunner> blocking_task_runner_; | 792 scoped_refptr<base::TaskRunner> blocking_task_runner_; |
670 | 793 |
671 // This value is used to identify how long to wait before starting a new run | 794 // This value is used to identify how long to wait before starting a new run |
672 // of the reporter. It's initialized with the default value and may be changed | 795 // of the reporter. It's initialized with the default value and may be changed |
673 // to a different value when a prompt is pending and the reporter should be | 796 // to a different value when a prompt is pending and the reporter should be |
674 // run before adding the global error to the Chrome menu. | 797 // run before adding the global error to the Chrome menu. |
675 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; | 798 int days_between_reporter_runs_ = kDaysBetweenSuccessfulSwReporterRuns; |
676 | 799 |
677 // A single leaky instance. | 800 // A single leaky instance. |
678 static ReporterRunner* instance_; | 801 static ReporterRunner* instance_; |
679 | 802 |
680 DISALLOW_COPY_AND_ASSIGN(ReporterRunner); | 803 DISALLOW_COPY_AND_ASSIGN(ReporterRunner); |
681 }; | 804 }; |
682 | 805 |
683 ReporterRunner* ReporterRunner::instance_ = nullptr; | 806 ReporterRunner* ReporterRunner::instance_ = nullptr; |
684 | 807 |
685 } // namespace | 808 } // namespace |
686 | 809 |
687 SwReporterInvocation::SwReporterInvocation() : command_line(0, nullptr) {} | 810 SwReporterInvocation::SwReporterInvocation() |
| 811 : command_line(0, nullptr), is_experimental(false) {} |
688 | 812 |
689 SwReporterInvocation::SwReporterInvocation(const base::FilePath& exe_path) | 813 SwReporterInvocation::SwReporterInvocation(const base::FilePath& exe_path) |
690 : command_line(exe_path) {} | 814 : command_line(exe_path), is_experimental(false) {} |
691 | 815 |
692 SwReporterInvocation::SwReporterInvocation( | 816 SwReporterInvocation::SwReporterInvocation( |
693 const base::CommandLine& command_line) | 817 const base::CommandLine& command_line) |
694 : command_line(command_line) {} | 818 : command_line(command_line), is_experimental(false) {} |
695 | 819 |
696 bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const { | 820 bool SwReporterInvocation::operator==(const SwReporterInvocation& other) const { |
697 return command_line.argv() == other.command_line.argv(); | 821 return command_line.argv() == other.command_line.argv() && |
| 822 suffix == other.suffix && is_experimental == other.is_experimental; |
698 } | 823 } |
699 | 824 |
700 void RunSwReporter(const SwReporterInvocation& invocation, | 825 void RunSwReporter(const SwReporterInvocation& invocation, |
701 const base::Version& version, | 826 const base::Version& version, |
702 scoped_refptr<base::TaskRunner> main_thread_task_runner, | 827 scoped_refptr<base::TaskRunner> main_thread_task_runner, |
703 scoped_refptr<base::TaskRunner> blocking_task_runner) { | 828 scoped_refptr<base::TaskRunner> blocking_task_runner) { |
704 ReporterRunner::Run(invocation, version, main_thread_task_runner, | 829 std::queue<SwReporterInvocation> invocations; |
| 830 invocations.push(invocation); |
| 831 ReporterRunner::Run(invocations, version, main_thread_task_runner, |
705 blocking_task_runner); | 832 blocking_task_runner); |
706 } | 833 } |
707 | 834 |
| 835 void RunSwReporters(const std::queue<SwReporterInvocation>& invocations, |
| 836 const base::Version& version, |
| 837 scoped_refptr<base::TaskRunner> main_thread_task_runner, |
| 838 scoped_refptr<base::TaskRunner> blocking_task_runner) { |
| 839 ReporterRunner::Run(invocations, version, main_thread_task_runner, |
| 840 blocking_task_runner); |
| 841 } |
| 842 |
708 bool ReporterFoundUws() { | 843 bool ReporterFoundUws() { |
709 PrefService* local_state = g_browser_process->local_state(); | 844 PrefService* local_state = g_browser_process->local_state(); |
710 if (!local_state) | 845 if (!local_state) |
711 return false; | 846 return false; |
712 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode); | 847 int exit_code = local_state->GetInteger(prefs::kSwReporterLastExitCode); |
713 return exit_code == kSwReporterCleanupNeeded; | 848 return exit_code == kSwReporterCleanupNeeded; |
714 } | 849 } |
715 | 850 |
716 bool UserHasRunCleaner() { | 851 bool UserHasRunCleaner() { |
717 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey); | 852 base::string16 cleaner_key_path(kSoftwareRemovalToolRegistryKey); |
(...skipping 15 matching lines...) Expand all Loading... |
733 | 868 |
734 void SetLaunchReadyNotifierForTesting(const LaunchReadyNotifier& notifier) { | 869 void SetLaunchReadyNotifierForTesting(const LaunchReadyNotifier& notifier) { |
735 g_launch_ready_notifier_ = notifier; | 870 g_launch_ready_notifier_ = notifier; |
736 } | 871 } |
737 | 872 |
738 void SetReporterDoneNotifierForTesting(const ReporterDoneNotifier& notifier) { | 873 void SetReporterDoneNotifierForTesting(const ReporterDoneNotifier& notifier) { |
739 g_reporter_done_notifier_ = notifier; | 874 g_reporter_done_notifier_ = notifier; |
740 } | 875 } |
741 | 876 |
742 } // namespace safe_browsing | 877 } // namespace safe_browsing |
OLD | NEW |