| 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 |