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"; |
Alexei Svitkine (slow)
2014/06/19 14:25:03
Nit: It's fine to inline these into the macros, ra
| |
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; |
128 environment_collection_task_runner_ = | 177 environment_collection_task_runner_ = |
129 content::BrowserThread::GetBlockingPool() | 178 content::BrowserThread::GetBlockingPool() |
130 ->GetTaskRunnerWithShutdownBehavior( | 179 ->GetTaskRunnerWithShutdownBehavior( |
131 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | 180 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
132 } | 181 } |
133 } | 182 } |
134 | 183 |
184 void IncidentReportingService::OnProfileCreated(Profile* profile) { | |
185 DCHECK(thread_checker_.CalledOnValidThread()); | |
186 | |
187 ProfileContext* context = GetOrCreateProfileContext(profile); | |
188 context->created = true; | |
189 | |
190 // Drop all incidents if this profile is not participating in safe browsing. | |
191 if (!context->incidents.empty() && | |
192 !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { | |
193 for (size_t i = 0; i < context->incidents.size(); ++i) { | |
194 LogIncidentDataType(DROPPED, *context->incidents[i]); | |
195 } | |
196 context->incidents.clear(); | |
197 } | |
198 } | |
199 | |
135 scoped_ptr<IncidentReportUploader> IncidentReportingService::StartReportUpload( | 200 scoped_ptr<IncidentReportUploader> IncidentReportingService::StartReportUpload( |
136 const IncidentReportUploader::OnResultCallback& callback, | 201 const IncidentReportUploader::OnResultCallback& callback, |
137 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, | 202 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, |
138 const ClientIncidentReport& report) { | 203 const ClientIncidentReport& report) { |
139 #if 0 | 204 #if 0 |
140 return IncidentReportUploaderImpl::UploadReport( | 205 return IncidentReportUploaderImpl::UploadReport( |
141 callback, request_context_getter, report).Pass(); | 206 callback, request_context_getter, report).Pass(); |
142 #else | 207 #else |
143 // TODO(grt): Remove this temporary suppression of all uploads. | 208 // TODO(grt): Remove this temporary suppression of all uploads. |
144 return scoped_ptr<IncidentReportUploader>(); | 209 return scoped_ptr<IncidentReportUploader>(); |
145 #endif | 210 #endif |
146 } | 211 } |
147 | 212 |
213 IncidentReportingService::ProfileContext* | |
214 IncidentReportingService::GetOrCreateProfileContext(Profile* profile) { | |
215 ProfileContextCollection::iterator it = | |
216 profiles_.insert(ProfileContextCollection::value_type(profile, NULL)) | |
217 .first; | |
218 if (!it->second) | |
219 it->second = new ProfileContext(); | |
220 return it->second; | |
221 } | |
222 | |
223 IncidentReportingService::ProfileContext* | |
224 IncidentReportingService::GetProfileContext(Profile* profile) { | |
225 ProfileContextCollection::iterator it = profiles_.find(profile); | |
226 return it == profiles_.end() ? NULL : it->second; | |
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 // It is forbidden to call this function with a destroyed profile. |
154 if (!enabled_) | 253 DCHECK(context); |
254 | |
255 // Drop the incident immediately if profile creation has completed and the | |
256 // profile is not participating in safe browsing. | |
257 if (context->created && | |
258 !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { | |
259 LogIncidentDataType(DROPPED, *incident_data); | |
155 return; | 260 return; |
261 } | |
156 | 262 |
263 // Create a new report if this is the first incident ever or first since last | |
264 // upload. | |
157 if (!report_) { | 265 if (!report_) { |
158 report_.reset(new ClientIncidentReport()); | 266 report_.reset(new ClientIncidentReport()); |
159 first_incident_time_ = base::Time::Now(); | 267 first_incident_time_ = base::Time::Now(); |
160 } | 268 } |
269 | |
270 // Provide time to the new incident if the caller didn't provide it. | |
161 if (!incident_data->has_incident_time_msec()) | 271 if (!incident_data->has_incident_time_msec()) |
162 incident_data->set_incident_time_msec(base::Time::Now().ToJavaTime()); | 272 incident_data->set_incident_time_msec(base::Time::Now().ToJavaTime()); |
163 report_->mutable_incident()->AddAllocated(incident_data.release()); | 273 |
274 // Take ownership of the incident. | |
275 context->incidents.push_back(incident_data.release()); | |
164 | 276 |
165 if (!last_incident_time_.is_null()) { | 277 if (!last_incident_time_.is_null()) { |
166 UMA_HISTOGRAM_TIMES("SBIRS.InterIncidentTime", | 278 UMA_HISTOGRAM_TIMES("SBIRS.InterIncidentTime", |
167 base::TimeTicks::Now() - last_incident_time_); | 279 base::TimeTicks::Now() - last_incident_time_); |
168 } | 280 } |
169 last_incident_time_ = base::TimeTicks::Now(); | 281 last_incident_time_ = base::TimeTicks::Now(); |
170 | 282 |
171 // Persist the incident data. | 283 // Persist the incident data. |
172 | 284 |
173 // Restart the delay timer to send the report upon expiration. | 285 // 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(); | 348 report_.reset(); |
237 } | 349 } |
238 | 350 |
239 void IncidentReportingService::OnCollectionTimeout() { | 351 void IncidentReportingService::OnCollectionTimeout() { |
240 DCHECK(thread_checker_.CalledOnValidThread()); | 352 DCHECK(thread_checker_.CalledOnValidThread()); |
241 | 353 |
242 // Exit early if collection was cancelled. | 354 // Exit early if collection was cancelled. |
243 if (!collection_timeout_pending_) | 355 if (!collection_timeout_pending_) |
244 return; | 356 return; |
245 | 357 |
358 // Wait another round if incidents have come in from a profile that has yet to | |
359 // complete creation. | |
360 for (ProfileContextCollection::iterator scan = profiles_.begin(); | |
361 scan != profiles_.end(); | |
362 ++scan) { | |
363 if (!scan->second->created && !scan->second->incidents.empty()) { | |
364 upload_timer_.Reset(); | |
365 return; | |
366 } | |
367 } | |
368 | |
246 collection_timeout_pending_ = false; | 369 collection_timeout_pending_ = false; |
247 | 370 |
248 UploadIfCollectionComplete(); | 371 UploadIfCollectionComplete(); |
249 } | 372 } |
250 | 373 |
251 void IncidentReportingService::CollectDownloadDetails( | 374 void IncidentReportingService::CollectDownloadDetails( |
252 ClientIncidentReport_DownloadDetails* download_details) { | 375 ClientIncidentReport_DownloadDetails* download_details) { |
253 DCHECK(thread_checker_.CalledOnValidThread()); | 376 DCHECK(thread_checker_.CalledOnValidThread()); |
254 // TODO(grt): collect download info; http://crbug.com/383042. | 377 // TODO(grt): collect download info; http://crbug.com/383042. |
255 } | 378 } |
(...skipping 10 matching lines...) Expand all Loading... | |
266 void IncidentReportingService::UploadIfCollectionComplete() { | 389 void IncidentReportingService::UploadIfCollectionComplete() { |
267 DCHECK(report_); | 390 DCHECK(report_); |
268 // Bail out if there are still outstanding collection tasks. | 391 // Bail out if there are still outstanding collection tasks. |
269 if (environment_collection_pending_ || collection_timeout_pending_) | 392 if (environment_collection_pending_ || collection_timeout_pending_) |
270 return; | 393 return; |
271 | 394 |
272 // Take ownership of the report and clear things for future reports. | 395 // Take ownership of the report and clear things for future reports. |
273 scoped_ptr<ClientIncidentReport> report(report_.Pass()); | 396 scoped_ptr<ClientIncidentReport> report(report_.Pass()); |
274 last_incident_time_ = base::TimeTicks(); | 397 last_incident_time_ = base::TimeTicks(); |
275 | 398 |
276 const int original_count = report->incident_size(); | 399 ClientIncidentReport_EnvironmentData_Process* process = |
277 UMA_HISTOGRAM_COUNTS_100("SBIRS.IncidentCount", original_count); | 400 report->mutable_environment()->mutable_process(); |
278 for (int i = 0; i < original_count; ++i) { | 401 |
279 LogIncidentDataType(report->incident(i)); | 402 // Not all platforms have a metrics reporting preference. |
403 if (g_browser_process->local_state()->FindPreference( | |
404 prefs::kMetricsReportingEnabled)) { | |
405 process->set_metrics_consent(g_browser_process->local_state()->GetBoolean( | |
406 prefs::kMetricsReportingEnabled)); | |
407 } | |
408 // Check for extended consent in any profile while collecting incidents. | |
409 process->set_extended_consent(false); | |
410 // Collect incidents across all profiles participating in safe browsing. Drop | |
411 // incidents if the profile stopped participating before collection completed. | |
412 for (ProfileContextCollection::iterator scan = profiles_.begin(); | |
413 scan != profiles_.end(); | |
414 ++scan) { | |
415 PrefService* prefs = scan->first->GetPrefs(); | |
416 if (process && | |
417 prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) { | |
418 process->set_extended_consent(true); | |
419 process = NULL; // Don't check any more once one is found. | |
420 } | |
421 ProfileContext* context = scan->second; | |
422 if (context->incidents.empty()) | |
423 continue; | |
424 if (prefs->GetBoolean(prefs::kSafeBrowsingEnabled)) { | |
425 for (size_t i = 0; i < context->incidents.size(); ++i) { | |
426 ClientIncidentReport_IncidentData* incident = context->incidents[i]; | |
427 LogIncidentDataType(ACCEPTED, *incident); | |
428 // Ownership of the incident is passed to the report. | |
429 report->mutable_incident()->AddAllocated(incident); | |
430 } | |
431 context->incidents.weak_clear(); | |
432 } else { | |
433 for (size_t i = 0; i < context->incidents.size(); ++i) { | |
434 LogIncidentDataType(DROPPED, *context->incidents[i]); | |
435 } | |
436 context->incidents.clear(); | |
437 } | |
280 } | 438 } |
281 | 439 |
440 const int original_count = report->incident_size(); | |
441 // Abandon the request if all incidents were dropped. | |
442 if (!original_count) | |
443 return; | |
444 | |
445 UMA_HISTOGRAM_COUNTS_100("SBIRS.IncidentCount", original_count); | |
446 | |
282 PruneReportedIncidents(report.get()); | 447 PruneReportedIncidents(report.get()); |
283 // TODO(grt): prune incidents from opted-out profiles; http://crbug.com/383039 | |
284 | 448 |
285 int final_count = report->incident_size(); | 449 int final_count = report->incident_size(); |
286 { | 450 { |
287 double prune_pct = static_cast<double>(original_count - final_count); | 451 double prune_pct = static_cast<double>(original_count - final_count); |
288 prune_pct = prune_pct * 100.0 / original_count; | 452 prune_pct = prune_pct * 100.0 / original_count; |
289 prune_pct = round(prune_pct); | 453 prune_pct = round(prune_pct); |
290 UMA_HISTOGRAM_PERCENTAGE("SBIRS.PruneRatio", static_cast<int>(prune_pct)); | 454 UMA_HISTOGRAM_PERCENTAGE("SBIRS.PruneRatio", static_cast<int>(prune_pct)); |
291 } | 455 } |
292 // Abandon the report if all incidents were pruned. | 456 // Abandon the report if all incidents were pruned. |
293 if (!final_count) | 457 if (!final_count) |
294 return; | 458 return; |
295 | 459 |
296 scoped_ptr<UploadContext> context(new UploadContext(report.Pass())); | 460 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_) { | 461 if (!database_manager_) { |
300 // No database manager during testing. Take ownership of the context and | 462 // No database manager during testing. Take ownership of the context and |
301 // continue processing. | 463 // continue processing. |
302 UploadContext* temp_context = context.get(); | 464 UploadContext* temp_context = context.get(); |
303 uploads_.push_back(context.release()); | 465 uploads_.push_back(context.release()); |
304 IncidentReportingService::OnKillSwitchResult(temp_context, false); | 466 IncidentReportingService::OnKillSwitchResult(temp_context, false); |
305 } else { | 467 } else { |
306 if (content::BrowserThread::PostTaskAndReplyWithResult( | 468 if (content::BrowserThread::PostTaskAndReplyWithResult( |
307 content::BrowserThread::IO, | 469 content::BrowserThread::IO, |
308 FROM_HERE, | 470 FROM_HERE, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 DCHECK(it != uploads_.end()); | 533 DCHECK(it != uploads_.end()); |
372 scoped_ptr<UploadContext> upload(context); // == *it | 534 scoped_ptr<UploadContext> upload(context); // == *it |
373 *it = uploads_.back(); | 535 *it = uploads_.back(); |
374 uploads_.weak_erase(uploads_.end() - 1); | 536 uploads_.weak_erase(uploads_.end() - 1); |
375 | 537 |
376 if (result == IncidentReportUploader::UPLOAD_SUCCESS) | 538 if (result == IncidentReportUploader::UPLOAD_SUCCESS) |
377 HandleResponse(upload->report.Pass(), response.Pass()); | 539 HandleResponse(upload->report.Pass(), response.Pass()); |
378 // else retry? | 540 // else retry? |
379 } | 541 } |
380 | 542 |
543 void IncidentReportingService::Observe( | |
544 int type, | |
545 const content::NotificationSource& source, | |
546 const content::NotificationDetails& details) { | |
547 switch (type) { | |
548 case chrome::NOTIFICATION_PROFILE_CREATED: { | |
549 Profile* profile = content::Source<Profile>(source).ptr(); | |
550 if (!profile->IsOffTheRecord()) | |
551 OnProfileCreated(profile); | |
552 break; | |
553 } | |
554 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | |
555 Profile* profile = content::Source<Profile>(source).ptr(); | |
556 if (!profile->IsOffTheRecord()) | |
557 OnProfileDestroyed(profile); | |
558 break; | |
559 } | |
560 default: | |
561 break; | |
562 } | |
563 } | |
564 | |
381 } // namespace safe_browsing | 565 } // namespace safe_browsing |
OLD | NEW |