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 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <string> | 11 #include <string> |
12 #include <utility> | 12 #include <utility> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
17 #include "base/metrics/field_trial.h" | 17 #include "base/metrics/field_trial.h" |
18 #include "base/metrics/histogram_macros.h" | 18 #include "base/metrics/histogram_macros.h" |
19 #include "base/process/process_info.h" | 19 #include "base/process/process_info.h" |
20 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
21 #include "base/stl_util.h" | |
22 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
23 #include "base/threading/sequenced_worker_pool.h" | 22 #include "base/threading/sequenced_worker_pool.h" |
24 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
25 #include "build/build_config.h" | 24 #include "build/build_config.h" |
26 #include "chrome/browser/chrome_notification_types.h" | 25 #include "chrome/browser/chrome_notification_types.h" |
27 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" | 26 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" |
28 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
29 #include "chrome/browser/safe_browsing/incident_reporting/environment_data_colle
ction.h" | 28 #include "chrome/browser/safe_browsing/incident_reporting/environment_data_colle
ction.h" |
30 #include "chrome/browser/safe_browsing/incident_reporting/extension_data_collect
ion.h" | 29 #include "chrome/browser/safe_browsing/incident_reporting/extension_data_collect
ion.h" |
31 #include "chrome/browser/safe_browsing/incident_reporting/incident.h" | 30 #include "chrome/browser/safe_browsing/incident_reporting/incident.h" |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 IncidentReportingService::~IncidentReportingService() { | 383 IncidentReportingService::~IncidentReportingService() { |
385 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 384 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
386 CancelIncidentCollection(); | 385 CancelIncidentCollection(); |
387 | 386 |
388 // Cancel all internal asynchronous tasks. | 387 // Cancel all internal asynchronous tasks. |
389 weak_ptr_factory_.InvalidateWeakPtrs(); | 388 weak_ptr_factory_.InvalidateWeakPtrs(); |
390 | 389 |
391 CancelEnvironmentCollection(); | 390 CancelEnvironmentCollection(); |
392 CancelDownloadCollection(); | 391 CancelDownloadCollection(); |
393 CancelAllReportUploads(); | 392 CancelAllReportUploads(); |
394 | |
395 base::STLDeleteValues(&profiles_); | |
396 } | 393 } |
397 | 394 |
398 std::unique_ptr<IncidentReceiver> | 395 std::unique_ptr<IncidentReceiver> |
399 IncidentReportingService::GetIncidentReceiver() { | 396 IncidentReportingService::GetIncidentReceiver() { |
400 return base::MakeUnique<Receiver>(receiver_weak_ptr_factory_.GetWeakPtr()); | 397 return base::MakeUnique<Receiver>(receiver_weak_ptr_factory_.GetWeakPtr()); |
401 } | 398 } |
402 | 399 |
403 std::unique_ptr<TrackedPreferenceValidationDelegate> | 400 std::unique_ptr<TrackedPreferenceValidationDelegate> |
404 IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) { | 401 IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) { |
405 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 402 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 return IncidentReportUploaderImpl::UploadReport( | 575 return IncidentReportUploaderImpl::UploadReport( |
579 callback, request_context_getter, report); | 576 callback, request_context_getter, report); |
580 } | 577 } |
581 | 578 |
582 bool IncidentReportingService::IsProcessingReport() const { | 579 bool IncidentReportingService::IsProcessingReport() const { |
583 return report_ != nullptr; | 580 return report_ != nullptr; |
584 } | 581 } |
585 | 582 |
586 IncidentReportingService::ProfileContext* | 583 IncidentReportingService::ProfileContext* |
587 IncidentReportingService::GetOrCreateProfileContext(Profile* profile) { | 584 IncidentReportingService::GetOrCreateProfileContext(Profile* profile) { |
588 ProfileContextCollection::iterator it = | 585 std::unique_ptr<ProfileContext>& context = profiles_[profile]; |
589 profiles_.insert(ProfileContextCollection::value_type(profile, nullptr)) | 586 if (!context) |
590 .first; | 587 context = base::MakeUnique<ProfileContext>(); |
591 if (!it->second) | 588 return context.get(); |
592 it->second = new ProfileContext(); | |
593 return it->second; | |
594 } | 589 } |
595 | 590 |
596 IncidentReportingService::ProfileContext* | 591 IncidentReportingService::ProfileContext* |
597 IncidentReportingService::GetProfileContext(Profile* profile) { | 592 IncidentReportingService::GetProfileContext(Profile* profile) { |
598 ProfileContextCollection::iterator it = profiles_.find(profile); | 593 auto it = profiles_.find(profile); |
599 return it != profiles_.end() ? it->second : nullptr; | 594 return it != profiles_.end() ? it->second.get() : nullptr; |
600 } | 595 } |
601 | 596 |
602 void IncidentReportingService::OnProfileDestroyed(Profile* profile) { | 597 void IncidentReportingService::OnProfileDestroyed(Profile* profile) { |
603 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 598 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
604 | 599 |
605 ProfileContextCollection::iterator it = profiles_.find(profile); | 600 auto it = profiles_.find(profile); |
606 if (it == profiles_.end()) | 601 if (it == profiles_.end()) |
607 return; | 602 return; |
608 | 603 |
609 // Take ownership of the context. | 604 // Take ownership of the context. |
610 std::unique_ptr<ProfileContext> context(it->second); | 605 std::unique_ptr<ProfileContext> context = std::move(it->second); |
611 it->second = nullptr; | 606 it->second = nullptr; |
612 | 607 |
613 // TODO(grt): Persist incidents for upload on future profile load. | 608 // TODO(grt): Persist incidents for upload on future profile load. |
614 | 609 |
615 // Remove the association with this profile context from all pending uploads. | 610 // Remove the association with this profile context from all pending uploads. |
616 for (const auto& upload : uploads_) | 611 for (const auto& upload : uploads_) |
617 upload->profiles_to_state.erase(context.get()); | 612 upload->profiles_to_state.erase(context.get()); |
618 | 613 |
619 // Forget about this profile. Incidents not yet sent for upload are lost. | 614 // Forget about this profile. Incidents not yet sent for upload are lost. |
620 // No new incidents will be accepted for it. | 615 // No new incidents will be accepted for it. |
621 profiles_.erase(it); | 616 profiles_.erase(it); |
622 } | 617 } |
623 | 618 |
624 Profile* IncidentReportingService::FindEligibleProfile() const { | 619 Profile* IncidentReportingService::FindEligibleProfile() const { |
625 Profile* candidate = nullptr; | 620 Profile* candidate = nullptr; |
626 for (ProfileContextCollection::const_iterator scan = profiles_.begin(); | 621 for (const auto& scan : profiles_) { |
627 scan != profiles_.end(); | |
628 ++scan) { | |
629 // Skip over profiles that have yet to be added to the profile manager. | 622 // Skip over profiles that have yet to be added to the profile manager. |
630 // This will also skip over the NULL-profile context used to hold | 623 // This will also skip over the NULL-profile context used to hold |
631 // process-wide incidents. | 624 // process-wide incidents. |
632 if (!scan->second->added) | 625 if (!scan.second->added) |
633 continue; | 626 continue; |
634 // Also skip over profiles for which IncidentReporting is not enabled. | 627 // Also skip over profiles for which IncidentReporting is not enabled. |
635 if (!IsEnabledForProfile(scan->first)) | 628 if (!IsEnabledForProfile(scan.first)) |
636 continue; | 629 continue; |
637 // If the current profile has Extended Reporting enabled, stop looking and | 630 // If the current profile has Extended Reporting enabled, stop looking and |
638 // use that one. | 631 // use that one. |
639 if (IsExtendedReportingEnabled(*scan->first->GetPrefs())) { | 632 if (IsExtendedReportingEnabled(*scan.first->GetPrefs())) { |
640 return scan->first; | 633 return scan.first; |
641 } | 634 } |
642 // Otherwise, store this one as a candidate and keep looking (in case we | 635 // Otherwise, store this one as a candidate and keep looking (in case we |
643 // find one with Extended Reporting enabled). | 636 // find one with Extended Reporting enabled). |
644 candidate = scan->first; | 637 candidate = scan.first; |
645 } | 638 } |
646 | 639 |
647 return candidate; | 640 return candidate; |
648 } | 641 } |
649 | 642 |
650 void IncidentReportingService::AddIncident(Profile* profile, | 643 void IncidentReportingService::AddIncident(Profile* profile, |
651 std::unique_ptr<Incident> incident) { | 644 std::unique_ptr<Incident> incident) { |
652 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 645 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
653 | 646 |
654 // Ignore incidents from off-the-record profiles. | 647 // Ignore incidents from off-the-record profiles. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 | 723 |
731 void IncidentReportingService::OnCollationTimeout() { | 724 void IncidentReportingService::OnCollationTimeout() { |
732 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 725 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
733 | 726 |
734 // Exit early if collection was cancelled. | 727 // Exit early if collection was cancelled. |
735 if (!collation_timeout_pending_) | 728 if (!collation_timeout_pending_) |
736 return; | 729 return; |
737 | 730 |
738 // Wait another round if profile-bound incidents have come in from a profile | 731 // Wait another round if profile-bound incidents have come in from a profile |
739 // that has yet to complete creation. | 732 // that has yet to complete creation. |
740 for (ProfileContextCollection::iterator scan = profiles_.begin(); | 733 for (const auto& scan : profiles_) { |
741 scan != profiles_.end(); ++scan) { | 734 if (scan.first && !scan.second->added && scan.second->HasIncidents()) { |
742 if (scan->first && !scan->second->added && scan->second->HasIncidents()) { | |
743 collation_timer_.Reset(); | 735 collation_timer_.Reset(); |
744 return; | 736 return; |
745 } | 737 } |
746 } | 738 } |
747 | 739 |
748 collation_timeout_pending_ = false; | 740 collation_timeout_pending_ = false; |
749 | 741 |
750 ProcessIncidentsIfCollectionComplete(); | 742 ProcessIncidentsIfCollectionComplete(); |
751 } | 743 } |
752 | 744 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 if (report_->has_download()) | 829 if (report_->has_download()) |
838 return false; | 830 return false; |
839 // The next easy case: waiting if the finder is operating. | 831 // The next easy case: waiting if the finder is operating. |
840 if (last_download_finder_) | 832 if (last_download_finder_) |
841 return true; | 833 return true; |
842 // Harder case 1: not waiting if there are no incidents to upload (only | 834 // Harder case 1: not waiting if there are no incidents to upload (only |
843 // incidents to clear). | 835 // incidents to clear). |
844 if (!HasIncidentsToUpload()) | 836 if (!HasIncidentsToUpload()) |
845 return false; | 837 return false; |
846 // Harder case 2: waiting if a non-NULL profile has not yet been added. | 838 // Harder case 2: waiting if a non-NULL profile has not yet been added. |
847 for (ProfileContextCollection::const_iterator scan = profiles_.begin(); | 839 for (const auto& scan : profiles_) { |
848 scan != profiles_.end(); | 840 if (scan.first && !scan.second->added) |
849 ++scan) { | |
850 if (scan->first && !scan->second->added) | |
851 return true; | 841 return true; |
852 } | 842 } |
853 // There is no most recent download and there's nothing more to wait for. | 843 // There is no most recent download and there's nothing more to wait for. |
854 return false; | 844 return false; |
855 } | 845 } |
856 | 846 |
857 void IncidentReportingService::CancelDownloadCollection() { | 847 void IncidentReportingService::CancelDownloadCollection() { |
858 last_download_finder_.reset(); | 848 last_download_finder_.reset(); |
859 last_download_begin_ = base::TimeTicks(); | 849 last_download_begin_ = base::TimeTicks(); |
860 if (report_) | 850 if (report_) |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 } | 927 } |
938 | 928 |
939 // Clear incidents data where needed. | 929 // Clear incidents data where needed. |
940 for (auto& profile_and_context : profiles_) { | 930 for (auto& profile_and_context : profiles_) { |
941 // Bypass process-wide incidents that have not yet been associated with a | 931 // Bypass process-wide incidents that have not yet been associated with a |
942 // profile and profiles with no incidents to clear. | 932 // profile and profiles with no incidents to clear. |
943 if (!profile_and_context.first || | 933 if (!profile_and_context.first || |
944 profile_and_context.second->incidents_to_clear.empty()) { | 934 profile_and_context.second->incidents_to_clear.empty()) { |
945 continue; | 935 continue; |
946 } | 936 } |
947 ProfileContext* context = profile_and_context.second; | 937 ProfileContext* context = profile_and_context.second.get(); |
948 StateStore::Transaction transaction(context->state_store.get()); | 938 StateStore::Transaction transaction(context->state_store.get()); |
949 for (const auto& incident : context->incidents_to_clear) | 939 for (const auto& incident : context->incidents_to_clear) |
950 transaction.Clear(incident->GetType(), incident->GetKey()); | 940 transaction.Clear(incident->GetType(), incident->GetKey()); |
951 context->incidents_to_clear.clear(); | 941 context->incidents_to_clear.clear(); |
952 } | 942 } |
953 // Abandon report if there are no incidents to upload. | 943 // Abandon report if there are no incidents to upload. |
954 if (!HasIncidentsToUpload()) | 944 if (!HasIncidentsToUpload()) |
955 return; | 945 return; |
956 | 946 |
957 bool has_download = | 947 bool has_download = |
958 report->has_download() || report->has_non_binary_download(); | 948 report->has_download() || report->has_non_binary_download(); |
959 | 949 |
960 // Collect incidents across all profiles participating in safe browsing. Drop | 950 // Collect incidents across all profiles participating in safe browsing. Drop |
961 // incidents if the profile stopped participating before collection completed. | 951 // incidents if the profile stopped participating before collection completed. |
962 // Prune previously submitted incidents. | 952 // Prune previously submitted incidents. |
963 // Associate the profile contexts and their incident data with the upload. | 953 // Associate the profile contexts and their incident data with the upload. |
964 UploadContext::PersistentIncidentStateCollection profiles_to_state; | 954 UploadContext::PersistentIncidentStateCollection profiles_to_state; |
965 for (auto& profile_and_context : profiles_) { | 955 for (auto& profile_and_context : profiles_) { |
966 // Bypass process-wide incidents that have not yet been associated with a | 956 // Bypass process-wide incidents that have not yet been associated with a |
967 // profile. | 957 // profile. |
968 if (!profile_and_context.first) | 958 if (!profile_and_context.first) |
969 continue; | 959 continue; |
970 ProfileContext* context = profile_and_context.second; | 960 ProfileContext* context = profile_and_context.second.get(); |
971 if (context->incidents.empty()) | 961 if (context->incidents.empty()) |
972 continue; | 962 continue; |
973 StateStore::Transaction transaction(context->state_store.get()); | 963 StateStore::Transaction transaction(context->state_store.get()); |
974 std::vector<PersistentIncidentState> states; | 964 std::vector<PersistentIncidentState> states; |
975 // Prep persistent data and prune any incidents already sent. | 965 // Prep persistent data and prune any incidents already sent. |
976 for (const auto& incident : context->incidents) { | 966 for (const auto& incident : context->incidents) { |
977 const PersistentIncidentState state = ComputeIncidentState(*incident); | 967 const PersistentIncidentState state = ComputeIncidentState(*incident); |
978 if (context->state_store->HasBeenReported(state.type, state.key, | 968 if (context->state_store->HasBeenReported(state.type, state.key, |
979 state.digest)) { | 969 state.digest)) { |
980 LogIncidentDataType(PRUNED, *incident); | 970 LogIncidentDataType(PRUNED, *incident); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 if (!profile->IsOffTheRecord()) | 1125 if (!profile->IsOffTheRecord()) |
1136 OnProfileDestroyed(profile); | 1126 OnProfileDestroyed(profile); |
1137 break; | 1127 break; |
1138 } | 1128 } |
1139 default: | 1129 default: |
1140 break; | 1130 break; |
1141 } | 1131 } |
1142 } | 1132 } |
1143 | 1133 |
1144 } // namespace safe_browsing | 1134 } // namespace safe_browsing |
OLD | NEW |