OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/incident_reporting_service.h" | 5 #include "chrome/browser/safe_browsing/incident_reporting_service.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/prefs/pref_service.h" | |
10 #include "base/process/process_info.h" | 11 #include "base/process/process_info.h" |
12 #include "base/stl_util.h" | |
11 #include "base/threading/sequenced_worker_pool.h" | 13 #include "base/threading/sequenced_worker_pool.h" |
14 #include "chrome/browser/browser_process.h" | |
15 #include "chrome/browser/chrome_notification_types.h" | |
12 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h" | 16 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h" |
17 #include "chrome/browser/profiles/profile.h" | |
13 #include "chrome/browser/safe_browsing/database_manager.h" | 18 #include "chrome/browser/safe_browsing/database_manager.h" |
14 #include "chrome/browser/safe_browsing/environment_data_collection.h" | 19 #include "chrome/browser/safe_browsing/environment_data_collection.h" |
15 #include "chrome/browser/safe_browsing/incident_report_uploader_impl.h" | 20 #include "chrome/browser/safe_browsing/incident_report_uploader_impl.h" |
16 #include "chrome/browser/safe_browsing/preference_validation_delegate.h" | 21 #include "chrome/browser/safe_browsing/preference_validation_delegate.h" |
17 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 22 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
23 #include "chrome/common/pref_names.h" | |
18 #include "chrome/common/safe_browsing/csd.pb.h" | 24 #include "chrome/common/safe_browsing/csd.pb.h" |
19 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/notification_service.h" | |
20 #include "net/url_request/url_request_context_getter.h" | 27 #include "net/url_request/url_request_context_getter.h" |
21 | 28 |
22 namespace safe_browsing { | 29 namespace safe_browsing { |
23 | 30 |
24 namespace { | 31 namespace { |
25 | 32 |
26 enum IncidentType { | 33 enum IncidentType { |
27 // Start with 1 rather than zero; otherwise there won't be enough buckets for | 34 // Start with 1 rather than zero; otherwise there won't be enough buckets for |
28 // the histogram. | 35 // the histogram. |
29 TRACKED_PREFERENCE = 1, | 36 TRACKED_PREFERENCE = 1, |
30 NUM_INCIDENT_TYPES | 37 NUM_INCIDENT_TYPES |
31 }; | 38 }; |
32 | 39 |
40 enum IncidentDisposition { | |
41 DROPPED, | |
42 ACCEPTED, | |
43 }; | |
44 | |
33 const int64 kDefaultUploadDelayMs = 1000 * 60; // one minute | 45 const int64 kDefaultUploadDelayMs = 1000 * 60; // one minute |
34 | 46 |
35 void LogIncidentDataType( | 47 void LogIncidentDataType( |
48 IncidentDisposition disposition, | |
36 const ClientIncidentReport_IncidentData& incident_data) { | 49 const ClientIncidentReport_IncidentData& incident_data) { |
37 if (incident_data.has_tracked_preference()) { | 50 static const char kAcceptedMetric[] = "SBIRS.Incident"; |
38 UMA_HISTOGRAM_ENUMERATION( | 51 static const char kDroppedMetric[] = "SBIRS.DroppedIncident"; |
39 "SBIRS.Incident", TRACKED_PREFERENCE, NUM_INCIDENT_TYPES); | 52 |
53 IncidentType type = TRACKED_PREFERENCE; | |
54 | |
55 // Add a switch statement once other types are supported. | |
56 DCHECK(incident_data.has_tracked_preference()); | |
57 | |
58 if (disposition == ACCEPTED) { | |
59 UMA_HISTOGRAM_ENUMERATION(kAcceptedMetric, type, NUM_INCIDENT_TYPES); | |
60 } else { | |
61 DCHECK_EQ(disposition, DROPPED); | |
62 UMA_HISTOGRAM_ENUMERATION(kDroppedMetric, type, NUM_INCIDENT_TYPES); | |
40 } | 63 } |
41 } | 64 } |
42 | 65 |
43 } // namespace | 66 } // namespace |
44 | 67 |
68 struct IncidentReportingService::ProfileContext { | |
69 ProfileContext(); | |
70 ~ProfileContext(); | |
71 | |
72 // The incidents collected for this profile pending creation and/or upload. | |
73 ScopedVector<ClientIncidentReport_IncidentData> incidents; | |
74 | |
75 // False until PROFILE_CREATED notification is received. | |
76 bool created; | |
77 | |
78 private: | |
79 DISALLOW_COPY_AND_ASSIGN(ProfileContext); | |
80 }; | |
81 | |
45 class IncidentReportingService::UploadContext { | 82 class IncidentReportingService::UploadContext { |
46 public: | 83 public: |
47 explicit UploadContext(scoped_ptr<ClientIncidentReport> report); | 84 explicit UploadContext(scoped_ptr<ClientIncidentReport> report); |
48 ~UploadContext(); | 85 ~UploadContext(); |
49 | 86 |
50 scoped_ptr<ClientIncidentReport> report; | 87 scoped_ptr<ClientIncidentReport> report; |
51 scoped_ptr<IncidentReportUploader> uploader; | 88 scoped_ptr<IncidentReportUploader> uploader; |
52 | 89 |
53 private: | 90 private: |
54 DISALLOW_COPY_AND_ASSIGN(UploadContext); | 91 DISALLOW_COPY_AND_ASSIGN(UploadContext); |
55 }; | 92 }; |
56 | 93 |
94 IncidentReportingService::ProfileContext::ProfileContext() : created() { | |
95 } | |
96 | |
97 IncidentReportingService::ProfileContext::~ProfileContext() { | |
98 } | |
99 | |
57 IncidentReportingService::UploadContext::UploadContext( | 100 IncidentReportingService::UploadContext::UploadContext( |
58 scoped_ptr<ClientIncidentReport> report) | 101 scoped_ptr<ClientIncidentReport> report) |
59 : report(report.Pass()) { | 102 : report(report.Pass()) { |
60 } | 103 } |
61 | 104 |
62 IncidentReportingService::UploadContext::~UploadContext() { | 105 IncidentReportingService::UploadContext::~UploadContext() { |
63 } | 106 } |
64 | 107 |
65 IncidentReportingService::IncidentReportingService( | 108 IncidentReportingService::IncidentReportingService( |
66 SafeBrowsingService* safe_browsing_service, | 109 SafeBrowsingService* safe_browsing_service, |
67 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter) | 110 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter) |
68 : database_manager_(safe_browsing_service ? | 111 : database_manager_(safe_browsing_service ? |
69 safe_browsing_service->database_manager() : NULL), | 112 safe_browsing_service->database_manager() : NULL), |
70 url_request_context_getter_(request_context_getter), | 113 url_request_context_getter_(request_context_getter), |
71 collect_environment_data_fn_(&CollectEnvironmentData), | 114 collect_environment_data_fn_(&CollectEnvironmentData), |
72 environment_collection_task_runner_( | 115 environment_collection_task_runner_( |
73 content::BrowserThread::GetBlockingPool() | 116 content::BrowserThread::GetBlockingPool() |
74 ->GetTaskRunnerWithShutdownBehavior( | 117 ->GetTaskRunnerWithShutdownBehavior( |
75 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), | 118 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
76 enabled_(), | |
77 environment_collection_pending_(), | 119 environment_collection_pending_(), |
78 collection_timeout_pending_(), | 120 collection_timeout_pending_(), |
79 upload_timer_(FROM_HERE, | 121 upload_timer_(FROM_HERE, |
80 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs), | 122 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs), |
81 this, | 123 this, |
82 &IncidentReportingService::OnCollectionTimeout), | 124 &IncidentReportingService::OnCollectionTimeout), |
83 receiver_weak_ptr_factory_(this), | 125 receiver_weak_ptr_factory_(this), |
84 weak_ptr_factory_(this) { | 126 weak_ptr_factory_(this) { |
127 notification_registrar_.Add(this, | |
128 chrome::NOTIFICATION_PROFILE_CREATED, | |
129 content::NotificationService::AllSources()); | |
130 notification_registrar_.Add(this, | |
131 chrome::NOTIFICATION_PROFILE_DESTROYED, | |
132 content::NotificationService::AllSources()); | |
85 } | 133 } |
86 | 134 |
87 IncidentReportingService::~IncidentReportingService() { | 135 IncidentReportingService::~IncidentReportingService() { |
88 if (enabled_) | 136 CancelIncidentCollection(); |
89 SetEnabled(false); | 137 |
138 // Cancel all internal asynchronous tasks. | |
139 weak_ptr_factory_.InvalidateWeakPtrs(); | |
140 | |
141 CancelEnvironmentCollection(); | |
142 CancelAllReportUploads(); | |
143 | |
144 STLDeleteValues(&profiles_); | |
90 } | 145 } |
91 | 146 |
92 void IncidentReportingService::SetEnabled(bool enabled) { | 147 AddIncidentCallback IncidentReportingService::GetAddIncidentCallback( |
93 DCHECK(thread_checker_.CalledOnValidThread()); | 148 Profile* profile) { |
149 // Force the context to be created so that incidents added before | |
150 // OnProfileCreated is called are held until the profile's preferences can be | |
151 // queried. | |
152 ignore_result(GetOrCreateProfileContext(profile)); | |
94 | 153 |
95 if (!enabled) { | |
96 CancelIncidentCollection(); | |
97 | |
98 // Cancel all internal asynchronous tasks. | |
99 weak_ptr_factory_.InvalidateWeakPtrs(); | |
100 | |
101 CancelEnvironmentCollection(); | |
102 CancelAllReportUploads(); | |
103 } | |
104 | |
105 enabled_ = enabled; | |
106 } | |
107 | |
108 AddIncidentCallback IncidentReportingService::GetAddIncidentCallback() { | |
109 return base::Bind(&IncidentReportingService::AddIncident, | 154 return base::Bind(&IncidentReportingService::AddIncident, |
110 receiver_weak_ptr_factory_.GetWeakPtr()); | 155 receiver_weak_ptr_factory_.GetWeakPtr(), |
156 profile); | |
111 } | 157 } |
112 | 158 |
113 scoped_ptr<TrackedPreferenceValidationDelegate> | 159 scoped_ptr<TrackedPreferenceValidationDelegate> |
114 IncidentReportingService::CreatePreferenceValidationDelegate() { | 160 IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) { |
115 DCHECK(thread_checker_.CalledOnValidThread()); | 161 DCHECK(thread_checker_.CalledOnValidThread()); |
162 | |
163 if (profile->IsOffTheRecord()) | |
164 return scoped_ptr<TrackedPreferenceValidationDelegate>(); | |
116 return scoped_ptr<TrackedPreferenceValidationDelegate>( | 165 return scoped_ptr<TrackedPreferenceValidationDelegate>( |
117 new PreferenceValidationDelegate(GetAddIncidentCallback())); | 166 new PreferenceValidationDelegate(GetAddIncidentCallback(profile))); |
118 } | 167 } |
119 | 168 |
120 void IncidentReportingService::SetCollectEnvironmentHook( | 169 void IncidentReportingService::SetCollectEnvironmentHook( |
121 CollectEnvironmentDataFn collect_environment_data_hook, | 170 CollectEnvironmentDataFn collect_environment_data_hook, |
122 const scoped_refptr<base::TaskRunner>& task_runner) { | 171 const scoped_refptr<base::TaskRunner>& task_runner) { |
123 if (collect_environment_data_hook) { | 172 if (collect_environment_data_hook) { |
124 collect_environment_data_fn_ = collect_environment_data_hook; | 173 collect_environment_data_fn_ = collect_environment_data_hook; |
125 environment_collection_task_runner_ = task_runner; | 174 environment_collection_task_runner_ = task_runner; |
126 } else { | 175 } else { |
127 collect_environment_data_fn_ = &CollectEnvironmentData; | 176 collect_environment_data_fn_ = &CollectEnvironmentData; |
(...skipping 10 matching lines...) Expand all Loading... | |
138 const ClientIncidentReport& report) { | 187 const ClientIncidentReport& report) { |
139 #if 0 | 188 #if 0 |
140 return IncidentReportUploaderImpl::UploadReport( | 189 return IncidentReportUploaderImpl::UploadReport( |
141 callback, request_context_getter, report).Pass(); | 190 callback, request_context_getter, report).Pass(); |
142 #else | 191 #else |
143 // TODO(grt): Remove this temporary suppression of all uploads. | 192 // TODO(grt): Remove this temporary suppression of all uploads. |
144 return scoped_ptr<IncidentReportUploader>(); | 193 return scoped_ptr<IncidentReportUploader>(); |
145 #endif | 194 #endif |
146 } | 195 } |
147 | 196 |
197 IncidentReportingService::ProfileContext* | |
198 IncidentReportingService::GetOrCreateProfileContext(Profile* profile) { | |
199 ProfileContextCollection::iterator it = | |
200 profiles_.insert(ProfileContextCollection::value_type(profile, NULL)) | |
201 .first; | |
202 if (!it->second) | |
203 it->second = new ProfileContext(); | |
204 return it->second; | |
205 } | |
206 | |
207 IncidentReportingService::ProfileContext* | |
208 IncidentReportingService::GetProfileContext(Profile* profile) { | |
209 ProfileContextCollection::iterator it = profiles_.find(profile); | |
210 return it == profiles_.end() ? NULL : it->second; | |
211 } | |
212 | |
213 void IncidentReportingService::OnProfileCreated(Profile* profile) { | |
214 DCHECK(thread_checker_.CalledOnValidThread()); | |
215 | |
216 ProfileContext* context = GetOrCreateProfileContext(profile); | |
217 context->created = true; | |
218 | |
219 // Drop all incidents if this profile is not participating in safe browsing. | |
220 if (!context->incidents.empty() && | |
221 !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { | |
222 for (size_t i = 0; i < context->incidents.size(); ++i) { | |
223 LogIncidentDataType(DROPPED, *context->incidents[i]); | |
224 } | |
225 context->incidents.clear(); | |
226 } | |
227 } | |
228 | |
229 void IncidentReportingService::OnProfileDestroyed(Profile* profile) { | |
230 DCHECK(thread_checker_.CalledOnValidThread()); | |
231 | |
232 ProfileContextCollection::iterator it = profiles_.find(profile); | |
233 if (it == profiles_.end()) | |
234 return; | |
235 | |
236 // TODO(grt): Persist incidents for upload on future profile load. | |
237 | |
238 // Forget about this profile. Incidents not yet sent for upload are lost. | |
239 // No new incidents will be accepted for it. | |
240 delete it->second; | |
241 profiles_.erase(it); | |
242 } | |
243 | |
148 void IncidentReportingService::AddIncident( | 244 void IncidentReportingService::AddIncident( |
245 Profile* profile, | |
149 scoped_ptr<ClientIncidentReport_IncidentData> incident_data) { | 246 scoped_ptr<ClientIncidentReport_IncidentData> incident_data) { |
150 DCHECK(thread_checker_.CalledOnValidThread()); | 247 DCHECK(thread_checker_.CalledOnValidThread()); |
248 // Incidents outside the context of a profile are not supported at the moment. | |
249 DCHECK(profile); | |
151 | 250 |
152 // TODO(grt): Don't ignore incidents that arrive before | 251 ProfileContext* context = GetProfileContext(profile); |
153 // NOTIFICATION_PROFILE_CREATED; http://crbug.com/383365. | 252 // The profile is unknown if it has already been destroyed. |
mattm
2014/06/18 21:07:18
Probably not safe to allow this to be called after
grt (UTC plus 2)
2014/06/18 22:47:58
The only case where GetProfileContext would return
mattm
2014/06/18 23:05:38
yeah, that sounds good. You could replace it with
grt (UTC plus 2)
2014/06/19 02:24:39
Done.
| |
154 if (!enabled_) | 253 if (!context) |
155 return; | 254 return; |
156 | 255 |
256 // Drop the incident immediately if profile creation has completed and the | |
257 // profile is not participating in safe browsing. | |
258 if (context->created && | |
259 !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { | |
260 LogIncidentDataType(DROPPED, *incident_data); | |
261 return; | |
262 } | |
263 | |
264 // Create a new report if this is the first incident ever or first since last | |
265 // upload. | |
157 if (!report_) { | 266 if (!report_) { |
158 report_.reset(new ClientIncidentReport()); | 267 report_.reset(new ClientIncidentReport()); |
159 first_incident_time_ = base::Time::Now(); | 268 first_incident_time_ = base::Time::Now(); |
160 } | 269 } |
270 | |
271 // Provide time to the new incident if the caller didn't provide it. | |
161 if (!incident_data->has_incident_time_msec()) | 272 if (!incident_data->has_incident_time_msec()) |
162 incident_data->set_incident_time_msec(base::Time::Now().ToJavaTime()); | 273 incident_data->set_incident_time_msec(base::Time::Now().ToJavaTime()); |
163 report_->mutable_incident()->AddAllocated(incident_data.release()); | 274 |
275 // Take ownership of the incident. | |
276 context->incidents.push_back(incident_data.release()); | |
164 | 277 |
165 if (!last_incident_time_.is_null()) { | 278 if (!last_incident_time_.is_null()) { |
166 UMA_HISTOGRAM_TIMES("SBIRS.InterIncidentTime", | 279 UMA_HISTOGRAM_TIMES("SBIRS.InterIncidentTime", |
167 base::TimeTicks::Now() - last_incident_time_); | 280 base::TimeTicks::Now() - last_incident_time_); |
168 } | 281 } |
169 last_incident_time_ = base::TimeTicks::Now(); | 282 last_incident_time_ = base::TimeTicks::Now(); |
170 | 283 |
171 // Persist the incident data. | 284 // Persist the incident data. |
172 | 285 |
173 // Restart the delay timer to send the report upon expiration. | 286 // Restart the delay timer to send the report upon expiration. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
236 report_.reset(); | 349 report_.reset(); |
237 } | 350 } |
238 | 351 |
239 void IncidentReportingService::OnCollectionTimeout() { | 352 void IncidentReportingService::OnCollectionTimeout() { |
240 DCHECK(thread_checker_.CalledOnValidThread()); | 353 DCHECK(thread_checker_.CalledOnValidThread()); |
241 | 354 |
242 // Exit early if collection was cancelled. | 355 // Exit early if collection was cancelled. |
243 if (!collection_timeout_pending_) | 356 if (!collection_timeout_pending_) |
244 return; | 357 return; |
245 | 358 |
359 // Wait another round if incidents have come in from a profile that has yet to | |
360 // complete creation. | |
361 for (ProfileContextCollection::iterator scan = profiles_.begin(); | |
362 scan != profiles_.end(); | |
363 ++scan) { | |
364 if (!scan->second->created && !scan->second->incidents.empty()) { | |
365 upload_timer_.Reset(); | |
366 return; | |
367 } | |
368 } | |
369 | |
246 collection_timeout_pending_ = false; | 370 collection_timeout_pending_ = false; |
247 | 371 |
248 UploadIfCollectionComplete(); | 372 UploadIfCollectionComplete(); |
249 } | 373 } |
250 | 374 |
251 void IncidentReportingService::CollectDownloadDetails( | 375 void IncidentReportingService::CollectDownloadDetails( |
252 ClientIncidentReport_DownloadDetails* download_details) { | 376 ClientIncidentReport_DownloadDetails* download_details) { |
253 DCHECK(thread_checker_.CalledOnValidThread()); | 377 DCHECK(thread_checker_.CalledOnValidThread()); |
254 // TODO(grt): collect download info; http://crbug.com/383042. | 378 // TODO(grt): collect download info; http://crbug.com/383042. |
255 } | 379 } |
(...skipping 10 matching lines...) Expand all Loading... | |
266 void IncidentReportingService::UploadIfCollectionComplete() { | 390 void IncidentReportingService::UploadIfCollectionComplete() { |
267 DCHECK(report_); | 391 DCHECK(report_); |
268 // Bail out if there are still outstanding collection tasks. | 392 // Bail out if there are still outstanding collection tasks. |
269 if (environment_collection_pending_ || collection_timeout_pending_) | 393 if (environment_collection_pending_ || collection_timeout_pending_) |
270 return; | 394 return; |
271 | 395 |
272 // Take ownership of the report and clear things for future reports. | 396 // Take ownership of the report and clear things for future reports. |
273 scoped_ptr<ClientIncidentReport> report(report_.Pass()); | 397 scoped_ptr<ClientIncidentReport> report(report_.Pass()); |
274 last_incident_time_ = base::TimeTicks(); | 398 last_incident_time_ = base::TimeTicks(); |
275 | 399 |
276 const int original_count = report->incident_size(); | 400 ClientIncidentReport_EnvironmentData_Process* process = |
277 UMA_HISTOGRAM_COUNTS_100("SBIRS.IncidentCount", original_count); | 401 report->mutable_environment()->mutable_process(); |
278 for (int i = 0; i < original_count; ++i) { | 402 |
279 LogIncidentDataType(report->incident(i)); | 403 // Not all platforms have a metrics reporting preference. |
404 if (g_browser_process->local_state()->FindPreference( | |
405 prefs::kMetricsReportingEnabled)) { | |
406 process->set_metrics_consent(g_browser_process->local_state()->GetBoolean( | |
407 prefs::kMetricsReportingEnabled)); | |
408 } | |
409 // Check for extended consent in any profile while collecting incidents. | |
410 process->set_extended_consent(false); | |
411 // Collect incidents across all profiles participating in safe browsing. Drop | |
412 // incidents if the profile stopped participating before collection completed. | |
413 for (ProfileContextCollection::iterator scan = profiles_.begin(); | |
414 scan != profiles_.end(); | |
415 ++scan) { | |
416 PrefService* prefs = scan->first->GetPrefs(); | |
417 if (process && | |
418 prefs->GetBoolean(prefs::kSafeBrowsingDownloadFeedbackEnabled)) { | |
mattm
2014/06/18 21:07:17
kSafeBrowsingExtendedReportingEnabled now
grt (UTC plus 2)
2014/06/18 22:47:58
thanks for the pointer.
grt (UTC plus 2)
2014/06/19 02:24:39
Done.
| |
419 process->set_extended_consent(true); | |
mattm
2014/06/18 21:07:18
is it okay that this isn't sent on a per-profile/i
grt (UTC plus 2)
2014/06/18 22:47:58
it is, thanks for checking.
| |
420 process = NULL; // Don't check any more once one is found. | |
421 } | |
422 ProfileContext* context = scan->second; | |
423 if (context->incidents.empty()) | |
424 continue; | |
425 if (prefs->GetBoolean(prefs::kSafeBrowsingEnabled)) { | |
426 for (size_t i = 0; i < context->incidents.size(); ++i) { | |
427 ClientIncidentReport_IncidentData* incident = context->incidents[i]; | |
428 LogIncidentDataType(ACCEPTED, *incident); | |
429 // Ownership of the incident is passed to the report. | |
430 report->mutable_incident()->AddAllocated(incident); | |
431 } | |
432 context->incidents.weak_clear(); | |
433 } else { | |
434 for (size_t i = 0; i < context->incidents.size(); ++i) { | |
435 LogIncidentDataType(DROPPED, *context->incidents[i]); | |
436 } | |
437 context->incidents.clear(); | |
438 } | |
280 } | 439 } |
281 | 440 |
441 const int original_count = report->incident_size(); | |
442 // Abandon the request if all incidents were dropped. | |
443 if (!original_count) | |
444 return; | |
445 | |
446 UMA_HISTOGRAM_COUNTS_100("SBIRS.IncidentCount", original_count); | |
447 | |
282 PruneReportedIncidents(report.get()); | 448 PruneReportedIncidents(report.get()); |
283 // TODO(grt): prune incidents from opted-out profiles; http://crbug.com/383039 | |
284 | 449 |
285 int final_count = report->incident_size(); | 450 int final_count = report->incident_size(); |
286 { | 451 { |
287 double prune_pct = static_cast<double>(original_count - final_count); | 452 double prune_pct = static_cast<double>(original_count - final_count); |
288 prune_pct = prune_pct * 100.0 / original_count; | 453 prune_pct = prune_pct * 100.0 / original_count; |
289 prune_pct = round(prune_pct); | 454 prune_pct = round(prune_pct); |
290 UMA_HISTOGRAM_PERCENTAGE("SBIRS.PruneRatio", static_cast<int>(prune_pct)); | 455 UMA_HISTOGRAM_PERCENTAGE("SBIRS.PruneRatio", static_cast<int>(prune_pct)); |
291 } | 456 } |
292 // Abandon the report if all incidents were pruned. | 457 // Abandon the report if all incidents were pruned. |
293 if (!final_count) | 458 if (!final_count) |
294 return; | 459 return; |
295 | 460 |
296 scoped_ptr<UploadContext> context(new UploadContext(report.Pass())); | 461 scoped_ptr<UploadContext> context(new UploadContext(report.Pass())); |
297 scoped_refptr<base::RefCountedData<bool> > is_killswitch_on( | |
298 new base::RefCountedData<bool>(false)); | |
299 if (!database_manager_) { | 462 if (!database_manager_) { |
300 // No database manager during testing. Take ownership of the context and | 463 // No database manager during testing. Take ownership of the context and |
301 // continue processing. | 464 // continue processing. |
302 UploadContext* temp_context = context.get(); | 465 UploadContext* temp_context = context.get(); |
303 uploads_.push_back(context.release()); | 466 uploads_.push_back(context.release()); |
304 IncidentReportingService::OnKillSwitchResult(temp_context, false); | 467 IncidentReportingService::OnKillSwitchResult(temp_context, false); |
305 } else { | 468 } else { |
306 if (content::BrowserThread::PostTaskAndReplyWithResult( | 469 if (content::BrowserThread::PostTaskAndReplyWithResult( |
307 content::BrowserThread::IO, | 470 content::BrowserThread::IO, |
308 FROM_HERE, | 471 FROM_HERE, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 DCHECK(it != uploads_.end()); | 534 DCHECK(it != uploads_.end()); |
372 scoped_ptr<UploadContext> upload(context); // == *it | 535 scoped_ptr<UploadContext> upload(context); // == *it |
373 *it = uploads_.back(); | 536 *it = uploads_.back(); |
374 uploads_.weak_erase(uploads_.end() - 1); | 537 uploads_.weak_erase(uploads_.end() - 1); |
375 | 538 |
376 if (result == IncidentReportUploader::UPLOAD_SUCCESS) | 539 if (result == IncidentReportUploader::UPLOAD_SUCCESS) |
377 HandleResponse(upload->report.Pass(), response.Pass()); | 540 HandleResponse(upload->report.Pass(), response.Pass()); |
378 // else retry? | 541 // else retry? |
379 } | 542 } |
380 | 543 |
544 void IncidentReportingService::Observe( | |
545 int type, | |
546 const content::NotificationSource& source, | |
547 const content::NotificationDetails& details) { | |
548 switch (type) { | |
549 case chrome::NOTIFICATION_PROFILE_CREATED: { | |
550 Profile* profile = content::Source<Profile>(source).ptr(); | |
551 if (!profile->IsOffTheRecord()) | |
552 OnProfileCreated(profile); | |
553 break; | |
554 } | |
555 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | |
556 Profile* profile = content::Source<Profile>(source).ptr(); | |
557 if (!profile->IsOffTheRecord()) | |
558 OnProfileDestroyed(profile); | |
559 break; | |
560 } | |
561 default: | |
562 break; | |
563 } | |
564 } | |
565 | |
381 } // namespace safe_browsing | 566 } // namespace safe_browsing |
OLD | NEW |