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/incident_reporting_ser
vice.h" | 5 #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_ser
vice.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <utility> | 10 #include <utility> |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 return state; | 109 return state; |
110 } | 110 } |
111 | 111 |
112 // Returns true if the incident reporting service field trial is enabled. | 112 // Returns true if the incident reporting service field trial is enabled. |
113 bool IsFieldTrialEnabled() { | 113 bool IsFieldTrialEnabled() { |
114 std::string group_name = base::FieldTrialList::FindFullName( | 114 std::string group_name = base::FieldTrialList::FindFullName( |
115 "SafeBrowsingIncidentReportingService"); | 115 "SafeBrowsingIncidentReportingService"); |
116 return base::StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE); | 116 return base::StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE); |
117 } | 117 } |
118 | 118 |
| 119 bool ProfileCanAcceptIncident(Profile* profile, const Incident& incident) { |
| 120 if (profile->IsOffTheRecord()) |
| 121 return false; |
| 122 if (!profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) |
| 123 return false; |
| 124 switch (incident.GetMinimumProfileConsent()) { |
| 125 case MinimumProfileConsent::SAFE_BROWSING_ENABLED: |
| 126 return true; |
| 127 case MinimumProfileConsent::SAFE_BROWSING_EXTENDED_REPORTING_ENABLED: |
| 128 return profile->GetPrefs()->GetBoolean( |
| 129 prefs::kSafeBrowsingExtendedReportingEnabled); |
| 130 } |
| 131 NOTREACHED(); |
| 132 return false; |
| 133 } |
| 134 |
119 } // namespace | 135 } // namespace |
120 | 136 |
121 struct IncidentReportingService::ProfileContext { | 137 struct IncidentReportingService::ProfileContext { |
122 ProfileContext(); | 138 ProfileContext(); |
123 ~ProfileContext(); | 139 ~ProfileContext(); |
124 | 140 |
125 // Returns true if the profile has incidents to be uploaded or cleared. | 141 // Returns true if the profile has incidents to be uploaded or cleared. |
126 bool HasIncidents() const; | 142 bool HasIncidents() const; |
127 | 143 |
128 // The incidents collected for this profile pending creation and/or upload. | 144 // The incidents collected for this profile pending creation and/or upload. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 scoped_ptr<Incident> incident) { | 224 scoped_ptr<Incident> incident) { |
209 DCHECK(thread_runner_->BelongsToCurrentThread()); | 225 DCHECK(thread_runner_->BelongsToCurrentThread()); |
210 DCHECK(profile); | 226 DCHECK(profile); |
211 AddIncidentOnMainThread(service_, profile, std::move(incident)); | 227 AddIncidentOnMainThread(service_, profile, std::move(incident)); |
212 } | 228 } |
213 | 229 |
214 void IncidentReportingService::Receiver::AddIncidentForProcess( | 230 void IncidentReportingService::Receiver::AddIncidentForProcess( |
215 scoped_ptr<Incident> incident) { | 231 scoped_ptr<Incident> incident) { |
216 if (thread_runner_->BelongsToCurrentThread()) { | 232 if (thread_runner_->BelongsToCurrentThread()) { |
217 AddIncidentOnMainThread(service_, nullptr, std::move(incident)); | 233 AddIncidentOnMainThread(service_, nullptr, std::move(incident)); |
218 } else if (!thread_runner_->PostTask( | 234 } else { |
219 FROM_HERE, | 235 thread_runner_->PostTask( |
220 base::Bind(&IncidentReportingService::Receiver::AddIncidentOnMainThread, | 236 FROM_HERE, |
221 service_, nullptr, base::Passed(&incident)))) { | 237 base::Bind(&IncidentReportingService::Receiver::AddIncidentOnMainThread, |
222 LogIncidentDataType(DISCARDED, *incident); | 238 service_, nullptr, base::Passed(&incident))); |
223 } | 239 } |
224 } | 240 } |
225 | 241 |
226 void IncidentReportingService::Receiver::ClearIncidentForProcess( | 242 void IncidentReportingService::Receiver::ClearIncidentForProcess( |
227 scoped_ptr<Incident> incident) { | 243 scoped_ptr<Incident> incident) { |
228 if (thread_runner_->BelongsToCurrentThread()) { | 244 if (thread_runner_->BelongsToCurrentThread()) { |
229 ClearIncidentOnMainThread(service_, nullptr, std::move(incident)); | 245 ClearIncidentOnMainThread(service_, nullptr, std::move(incident)); |
230 } else { | 246 } else { |
231 thread_runner_->PostTask( | 247 thread_runner_->PostTask( |
232 FROM_HERE, | 248 FROM_HERE, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 collation_timeout_pending_(), | 329 collation_timeout_pending_(), |
314 collation_timer_(FROM_HERE, | 330 collation_timer_(FROM_HERE, |
315 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs), | 331 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs), |
316 this, | 332 this, |
317 &IncidentReportingService::OnCollationTimeout), | 333 &IncidentReportingService::OnCollationTimeout), |
318 delayed_analysis_callbacks_( | 334 delayed_analysis_callbacks_( |
319 base::TimeDelta::FromMilliseconds(kDefaultCallbackIntervalMs), | 335 base::TimeDelta::FromMilliseconds(kDefaultCallbackIntervalMs), |
320 content::BrowserThread::GetBlockingPool() | 336 content::BrowserThread::GetBlockingPool() |
321 ->GetTaskRunnerWithShutdownBehavior( | 337 ->GetTaskRunnerWithShutdownBehavior( |
322 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), | 338 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
| 339 extended_reporting_only_delayed_analysis_callbacks_( |
| 340 base::TimeDelta::FromMilliseconds(kDefaultCallbackIntervalMs), |
| 341 content::BrowserThread::GetBlockingPool() |
| 342 ->GetTaskRunnerWithShutdownBehavior( |
| 343 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
323 download_metadata_manager_(content::BrowserThread::GetBlockingPool()), | 344 download_metadata_manager_(content::BrowserThread::GetBlockingPool()), |
324 receiver_weak_ptr_factory_(this), | 345 receiver_weak_ptr_factory_(this), |
325 weak_ptr_factory_(this) { | 346 weak_ptr_factory_(this) { |
326 notification_registrar_.Add(this, | 347 notification_registrar_.Add(this, |
327 chrome::NOTIFICATION_PROFILE_ADDED, | 348 chrome::NOTIFICATION_PROFILE_ADDED, |
328 content::NotificationService::AllSources()); | 349 content::NotificationService::AllSources()); |
329 notification_registrar_.Add(this, | 350 notification_registrar_.Add(this, |
330 chrome::NOTIFICATION_PROFILE_DESTROYED, | 351 chrome::NOTIFICATION_PROFILE_DESTROYED, |
331 content::NotificationService::AllSources()); | 352 content::NotificationService::AllSources()); |
332 DownloadProtectionService* download_protection_service = | 353 DownloadProtectionService* download_protection_service = |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 delayed_analysis_callbacks_.RegisterCallback( | 401 delayed_analysis_callbacks_.RegisterCallback( |
381 base::Bind(callback, base::Passed(GetIncidentReceiver()))); | 402 base::Bind(callback, base::Passed(GetIncidentReceiver()))); |
382 | 403 |
383 // Start running the callbacks if any profiles are participating in safe | 404 // Start running the callbacks if any profiles are participating in safe |
384 // browsing. If none are now, running will commence if/when a participaing | 405 // browsing. If none are now, running will commence if/when a participaing |
385 // profile is added. | 406 // profile is added. |
386 if (FindEligibleProfile()) | 407 if (FindEligibleProfile()) |
387 delayed_analysis_callbacks_.Start(); | 408 delayed_analysis_callbacks_.Start(); |
388 } | 409 } |
389 | 410 |
| 411 void IncidentReportingService:: |
| 412 RegisterExtendedReportingOnlyDelayedAnalysisCallback( |
| 413 const DelayedAnalysisCallback& callback) { |
| 414 DCHECK(thread_checker_.CalledOnValidThread()); |
| 415 |
| 416 // |callback| will be run on the blocking pool. The receiver will bounce back |
| 417 // to the origin thread if needed. |
| 418 extended_reporting_only_delayed_analysis_callbacks_.RegisterCallback( |
| 419 base::Bind(callback, base::Passed(GetIncidentReceiver()))); |
| 420 |
| 421 // Start running the callbacks if any profiles have opted into Safebrowsing |
| 422 // extended reporting. If none are now, running will commence if/when such a |
| 423 // profile is added. |
| 424 Profile* profile = FindEligibleProfile(); |
| 425 if (profile && |
| 426 profile->GetPrefs()->GetBoolean( |
| 427 prefs::kSafeBrowsingExtendedReportingEnabled)) { |
| 428 extended_reporting_only_delayed_analysis_callbacks_.Start(); |
| 429 } |
| 430 } |
| 431 |
390 void IncidentReportingService::AddDownloadManager( | 432 void IncidentReportingService::AddDownloadManager( |
391 content::DownloadManager* download_manager) { | 433 content::DownloadManager* download_manager) { |
392 download_metadata_manager_.AddDownloadManager(download_manager); | 434 download_metadata_manager_.AddDownloadManager(download_manager); |
393 } | 435 } |
394 | 436 |
395 IncidentReportingService::IncidentReportingService( | 437 IncidentReportingService::IncidentReportingService( |
396 SafeBrowsingService* safe_browsing_service, | 438 SafeBrowsingService* safe_browsing_service, |
397 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, | 439 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, |
398 base::TimeDelta delayed_task_interval, | 440 base::TimeDelta delayed_task_interval, |
399 const scoped_refptr<base::TaskRunner>& delayed_task_runner) | 441 const scoped_refptr<base::TaskRunner>& delayed_task_runner) |
400 : database_manager_(safe_browsing_service | 442 : database_manager_(safe_browsing_service |
401 ? safe_browsing_service->database_manager() | 443 ? safe_browsing_service->database_manager() |
402 : NULL), | 444 : NULL), |
403 url_request_context_getter_(request_context_getter), | 445 url_request_context_getter_(request_context_getter), |
404 collect_environment_data_fn_(&CollectEnvironmentData), | 446 collect_environment_data_fn_(&CollectEnvironmentData), |
405 environment_collection_task_runner_( | 447 environment_collection_task_runner_( |
406 content::BrowserThread::GetBlockingPool() | 448 content::BrowserThread::GetBlockingPool() |
407 ->GetTaskRunnerWithShutdownBehavior( | 449 ->GetTaskRunnerWithShutdownBehavior( |
408 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), | 450 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
409 environment_collection_pending_(), | 451 environment_collection_pending_(), |
410 collation_timeout_pending_(), | 452 collation_timeout_pending_(), |
411 collation_timer_(FROM_HERE, | 453 collation_timer_(FROM_HERE, |
412 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs), | 454 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs), |
413 this, | 455 this, |
414 &IncidentReportingService::OnCollationTimeout), | 456 &IncidentReportingService::OnCollationTimeout), |
415 delayed_analysis_callbacks_(delayed_task_interval, delayed_task_runner), | 457 delayed_analysis_callbacks_(delayed_task_interval, delayed_task_runner), |
| 458 extended_reporting_only_delayed_analysis_callbacks_(delayed_task_interval, |
| 459 delayed_task_runner), |
416 download_metadata_manager_(content::BrowserThread::GetBlockingPool()), | 460 download_metadata_manager_(content::BrowserThread::GetBlockingPool()), |
417 receiver_weak_ptr_factory_(this), | 461 receiver_weak_ptr_factory_(this), |
418 weak_ptr_factory_(this) { | 462 weak_ptr_factory_(this) { |
419 enabled_by_field_trial_ = IsFieldTrialEnabled(); | 463 enabled_by_field_trial_ = IsFieldTrialEnabled(); |
420 | 464 |
421 notification_registrar_.Add(this, | 465 notification_registrar_.Add(this, |
422 chrome::NOTIFICATION_PROFILE_ADDED, | 466 chrome::NOTIFICATION_PROFILE_ADDED, |
423 content::NotificationService::AllSources()); | 467 content::NotificationService::AllSources()); |
424 notification_registrar_.Add(this, | 468 notification_registrar_.Add(this, |
425 chrome::NOTIFICATION_PROFILE_DESTROYED, | 469 chrome::NOTIFICATION_PROFILE_DESTROYED, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 LogIncidentDataType(DROPPED, *incident); | 509 LogIncidentDataType(DROPPED, *incident); |
466 context->incidents.clear(); | 510 context->incidents.clear(); |
467 } | 511 } |
468 | 512 |
469 if (enabled_for_profile) { | 513 if (enabled_for_profile) { |
470 // Start processing delayed analysis callbacks if incident reporting is | 514 // Start processing delayed analysis callbacks if incident reporting is |
471 // enabled for this new profile. Start is idempotent, so this is safe even | 515 // enabled for this new profile. Start is idempotent, so this is safe even |
472 // if they're already running. | 516 // if they're already running. |
473 delayed_analysis_callbacks_.Start(); | 517 delayed_analysis_callbacks_.Start(); |
474 | 518 |
| 519 if (profile->GetPrefs()->GetBoolean( |
| 520 prefs::kSafeBrowsingExtendedReportingEnabled)) { |
| 521 extended_reporting_only_delayed_analysis_callbacks_.Start(); |
| 522 } |
| 523 |
475 // Start a new report if there are process-wide incidents, or incidents for | 524 // Start a new report if there are process-wide incidents, or incidents for |
476 // this profile. | 525 // this profile. |
477 if ((GetProfileContext(nullptr) && | 526 if ((GetProfileContext(nullptr) && |
478 GetProfileContext(nullptr)->HasIncidents()) || | 527 GetProfileContext(nullptr)->HasIncidents()) || |
479 context->HasIncidents()) { | 528 context->HasIncidents()) { |
480 BeginReportProcessing(); | 529 BeginReportProcessing(); |
481 } | 530 } |
482 } | 531 } |
483 | 532 |
484 // TODO(grt): register for pref change notifications to start delayed analysis | 533 // TODO(grt): register for pref change notifications to start delayed analysis |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 // Associate the profile contexts and their incident data with the upload. | 950 // Associate the profile contexts and their incident data with the upload. |
902 UploadContext::PersistentIncidentStateCollection profiles_to_state; | 951 UploadContext::PersistentIncidentStateCollection profiles_to_state; |
903 for (auto& profile_and_context : profiles_) { | 952 for (auto& profile_and_context : profiles_) { |
904 // Bypass process-wide incidents that have not yet been associated with a | 953 // Bypass process-wide incidents that have not yet been associated with a |
905 // profile. | 954 // profile. |
906 if (!profile_and_context.first) | 955 if (!profile_and_context.first) |
907 continue; | 956 continue; |
908 ProfileContext* context = profile_and_context.second; | 957 ProfileContext* context = profile_and_context.second; |
909 if (context->incidents.empty()) | 958 if (context->incidents.empty()) |
910 continue; | 959 continue; |
911 if (!IsEnabledForProfile(profile_and_context.first)) { | |
912 for (const auto& incident : context->incidents) | |
913 LogIncidentDataType(DROPPED, *incident); | |
914 context->incidents.clear(); | |
915 continue; | |
916 } | |
917 StateStore::Transaction transaction(context->state_store.get()); | 960 StateStore::Transaction transaction(context->state_store.get()); |
918 std::vector<PersistentIncidentState> states; | 961 std::vector<PersistentIncidentState> states; |
919 // Prep persistent data and prune any incidents already sent. | 962 // Prep persistent data and prune any incidents already sent. |
920 for (const auto& incident : context->incidents) { | 963 for (const auto& incident : context->incidents) { |
921 const PersistentIncidentState state = ComputeIncidentState(*incident); | 964 const PersistentIncidentState state = ComputeIncidentState(*incident); |
922 if (context->state_store->HasBeenReported(state.type, state.key, | 965 if (context->state_store->HasBeenReported(state.type, state.key, |
923 state.digest)) { | 966 state.digest)) { |
924 LogIncidentDataType(PRUNED, *incident); | 967 LogIncidentDataType(PRUNED, *incident); |
| 968 } else if (!ProfileCanAcceptIncident(profile_and_context.first, |
| 969 *incident)) { |
| 970 LogIncidentDataType(DROPPED, *incident); |
925 } else if (!has_download) { | 971 } else if (!has_download) { |
926 LogIncidentDataType(NO_DOWNLOAD, *incident); | 972 LogIncidentDataType(NO_DOWNLOAD, *incident); |
927 // Drop the incident and mark for future pruning since no executable | 973 // Drop the incident and mark for future pruning since no executable |
928 // download was found. | 974 // download was found. |
929 transaction.MarkAsReported(state.type, state.key, state.digest); | 975 transaction.MarkAsReported(state.type, state.key, state.digest); |
930 } else { | 976 } else { |
931 LogIncidentDataType(ACCEPTED, *incident); | 977 LogIncidentDataType(ACCEPTED, *incident); |
932 // Ownership of the payload is passed to the report. | 978 // Ownership of the payload is passed to the report. |
933 ClientIncidentReport_IncidentData* data = | 979 ClientIncidentReport_IncidentData* data = |
934 incident->TakePayload().release(); | 980 incident->TakePayload().release(); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 if (!profile->IsOffTheRecord()) | 1116 if (!profile->IsOffTheRecord()) |
1071 OnProfileDestroyed(profile); | 1117 OnProfileDestroyed(profile); |
1072 break; | 1118 break; |
1073 } | 1119 } |
1074 default: | 1120 default: |
1075 break; | 1121 break; |
1076 } | 1122 } |
1077 } | 1123 } |
1078 | 1124 |
1079 } // namespace safe_browsing | 1125 } // namespace safe_browsing |
OLD | NEW |