| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h" |
| |
| #include <stdint.h> |
| |
| #include <map> |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/lazy_instance.h" |
| #include "base/macros.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/mock_entropy_provider.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/scoped_mock_time_message_loop_task_runner.h" |
| #include "base/threading/thread_local.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/values.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/prefs/browser_prefs.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/incident.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/incident_report_uploader.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/last_download_finder.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "components/safe_browsing/common/safe_browsing_prefs.h" |
| #include "components/safe_browsing/proto/csd.pb.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "extensions/browser/quota_service.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| #if defined(OS_WIN) |
| #include "base/test/test_reg_util_win.h" |
| #endif |
| |
| // A test fixture that sets up a test task runner and makes it the thread's |
| // runner. The fixture implements a fake environment data collector, extension |
| // data collector and a fake report uploader. |
| class IncidentReportingServiceTest : public testing::Test { |
| protected: |
| // An IRS class that allows a test harness to provide a fake environment |
| // collector, extension collector and report uploader via callbacks. |
| class TestIncidentReportingService |
| : public safe_browsing::IncidentReportingService { |
| public: |
| using PreProfileAddCallback = base::Callback<void(Profile*)>; |
| |
| using CollectEnvironmentCallback = base::Callback<void( |
| safe_browsing::ClientIncidentReport_EnvironmentData*)>; |
| |
| using CreateDownloadFinderCallback = |
| base::Callback<std::unique_ptr<safe_browsing::LastDownloadFinder>( |
| const safe_browsing::LastDownloadFinder::LastDownloadCallback& |
| callback)>; |
| |
| using StartUploadCallback = |
| base::Callback<std::unique_ptr<safe_browsing::IncidentReportUploader>( |
| const safe_browsing::IncidentReportUploader::OnResultCallback&, |
| const safe_browsing::ClientIncidentReport& report)>; |
| |
| TestIncidentReportingService( |
| const scoped_refptr<base::TaskRunner>& task_runner, |
| const PreProfileAddCallback& pre_profile_add_callback, |
| const CollectEnvironmentCallback& collect_environment_callback, |
| const CreateDownloadFinderCallback& create_download_finder_callback, |
| const StartUploadCallback& start_upload_callback) |
| : IncidentReportingService(nullptr, |
| base::TimeDelta::FromMilliseconds(5), |
| task_runner), |
| pre_profile_add_callback_(pre_profile_add_callback), |
| collect_environment_callback_(collect_environment_callback), |
| create_download_finder_callback_(create_download_finder_callback), |
| start_upload_callback_(start_upload_callback), |
| extension_collected_(false) { |
| SetCollectEnvironmentHook(&CollectEnvironmentData, task_runner); |
| test_instance_.Get().Set(this); |
| } |
| |
| ~TestIncidentReportingService() override { |
| test_instance_.Get().Set(nullptr); |
| } |
| |
| bool IsProcessingReport() const { |
| return IncidentReportingService::IsProcessingReport(); |
| } |
| |
| bool HasCollectedExtension() const { return extension_collected_; } |
| |
| protected: |
| void OnProfileAdded(Profile* profile) override { |
| pre_profile_add_callback_.Run(profile); |
| safe_browsing::IncidentReportingService::OnProfileAdded(profile); |
| } |
| |
| // A fake extension collection implementation invoked by the service during |
| // operation. |
| void DoExtensionCollection( |
| safe_browsing::ClientIncidentReport_ExtensionData* data) override { |
| ASSERT_NE(static_cast<safe_browsing::ClientIncidentReport_ExtensionData*>( |
| nullptr), |
| data); |
| data->mutable_last_installed_extension()->set_id(kFakeExtensionId); |
| extension_collected_ = true; |
| } |
| |
| std::unique_ptr<safe_browsing::LastDownloadFinder> CreateDownloadFinder( |
| const safe_browsing::LastDownloadFinder::LastDownloadCallback& callback) |
| override { |
| return create_download_finder_callback_.Run(callback); |
| } |
| |
| std::unique_ptr<safe_browsing::IncidentReportUploader> StartReportUpload( |
| const safe_browsing::IncidentReportUploader::OnResultCallback& callback, |
| const safe_browsing::ClientIncidentReport& report) override { |
| return start_upload_callback_.Run(callback, report); |
| } |
| |
| private: |
| static TestIncidentReportingService& current() { |
| return *test_instance_.Get().Get(); |
| } |
| |
| static void CollectEnvironmentData( |
| safe_browsing::ClientIncidentReport_EnvironmentData* data) { |
| current().collect_environment_callback_.Run(data); |
| } |
| |
| static base::LazyInstance<base::ThreadLocalPointer< |
| TestIncidentReportingService> >::Leaky test_instance_; |
| |
| PreProfileAddCallback pre_profile_add_callback_; |
| CollectEnvironmentCallback collect_environment_callback_; |
| CreateDownloadFinderCallback create_download_finder_callback_; |
| StartUploadCallback start_upload_callback_; |
| bool extension_collected_; |
| }; |
| |
| // A type for specifying whether a profile created by CreateProfile |
| // participates in safe browsing and safe browsing extended reporting. |
| enum SafeBrowsingDisposition { |
| OPT_OUT, |
| SAFE_BROWSING_ONLY, |
| EXTENDED_REPORTING_ONLY, |
| SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| }; |
| |
| // A type for specifying the action to be taken by the test fixture during |
| // profile initialization (before NOTIFICATION_PROFILE_ADDED is sent). |
| enum OnProfileAdditionAction { |
| ON_PROFILE_ADDITION_NO_ACTION, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, // Add an incident to the service. |
| ON_PROFILE_ADDITION_ADD_TWO_INCIDENTS, // Add two incidents to the service. |
| }; |
| |
| // A type for specifying the action to be taken by the test fixture when the |
| // service creates a LastDownloadFinder. |
| enum OnCreateDownloadFinderAction { |
| // Post a task that reports a binary and non-binary download. |
| ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND, |
| // Post a task that reports a binary download. |
| ON_CREATE_DOWNLOAD_FINDER_BINARY_DOWNLOAD_FOUND, |
| // Post a task that reports a non-binary download. |
| ON_CREATE_DOWNLOAD_FINDER_NON_BINARY_DOWNLOAD_FOUND, |
| // Post a task that reports no downloads found. |
| ON_CREATE_DOWNLOAD_FINDER_NO_DOWNLOADS, |
| // Immediately return due to a lack of eligible profiles. |
| ON_CREATE_DOWNLOAD_FINDER_NO_PROFILES, |
| }; |
| |
| // A type for specifying the action to be taken by the test fixture when its |
| // delayed analysis callback is run. |
| enum OnDelayedAnalysisAction { |
| ON_DELAYED_ANALYSIS_NO_ACTION, |
| ON_DELAYED_ANALYSIS_ADD_INCIDENT, // Add an incident to the service. |
| }; |
| |
| static const char kFakeOsName[]; |
| static const char kFakeDownloadToken[]; |
| static const char kFakeDownloadHost[]; |
| static const char kTestTrackedPrefPath[]; |
| static const char kFakeExtensionId[]; |
| |
| IncidentReportingServiceTest() |
| : profile_manager_(TestingBrowserProcess::GetGlobal()), |
| on_create_download_finder_action_( |
| ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND), |
| on_delayed_analysis_action_(ON_DELAYED_ANALYSIS_NO_ACTION), |
| upload_result_(safe_browsing::IncidentReportUploader::UPLOAD_SUCCESS), |
| environment_collected_(), |
| download_finder_created_(), |
| download_finder_destroyed_(), |
| uploader_destroyed_(), |
| delayed_analysis_ran_() {} |
| |
| void SetUp() override { |
| testing::Test::SetUp(); |
| #if defined(OS_WIN) |
| // Redirect HKCU so that the platform state store used by the test doesn't |
| // collide with existing Chrome installs or other tests running in parallel. |
| ASSERT_NO_FATAL_FAILURE( |
| registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER)); |
| #endif |
| ASSERT_TRUE(profile_manager_.SetUp()); |
| } |
| |
| void CreateIncidentReportingService() { |
| scoped_feature_list_.InitAndEnableFeature( |
| safe_browsing::kIncidentReportingEnableUpload); |
| |
| instance_.reset(new TestIncidentReportingService( |
| base::ThreadTaskRunnerHandle::Get(), |
| base::Bind(&IncidentReportingServiceTest::PreProfileAdd, |
| base::Unretained(this)), |
| base::Bind(&IncidentReportingServiceTest::CollectEnvironmentData, |
| base::Unretained(this)), |
| base::Bind(&IncidentReportingServiceTest::CreateDownloadFinder, |
| base::Unretained(this)), |
| base::Bind(&IncidentReportingServiceTest::StartUpload, |
| base::Unretained(this)))); |
| } |
| |
| // Sets the action to be taken by the test fixture when the service creates a |
| // LastDownloadFinder. |
| void SetCreateDownloadFinderAction(OnCreateDownloadFinderAction action) { |
| on_create_download_finder_action_ = action; |
| } |
| |
| // Creates and returns a profile (owned by the profile manager) with or |
| // without safe browsing enabled. An incident will be created within |
| // PreProfileAdd if requested. |incidents_sent|, if provided, will be set |
| // in the profile's preference. |
| TestingProfile* CreateProfile(const std::string& profile_name, |
| SafeBrowsingDisposition safe_browsing_opt_in, |
| OnProfileAdditionAction on_addition_action, |
| std::unique_ptr<base::Value> incidents_sent) { |
| // Create prefs for the profile with safe browsing enabled or not. |
| std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs( |
| new sync_preferences::TestingPrefServiceSyncable); |
| RegisterUserProfilePrefs(prefs->registry()); |
| prefs->SetBoolean( |
| prefs::kSafeBrowsingEnabled, |
| safe_browsing_opt_in == SAFE_BROWSING_ONLY || |
| safe_browsing_opt_in == SAFE_BROWSING_AND_EXTENDED_REPORTING); |
| safe_browsing::SetExtendedReportingPref( |
| prefs.get(), |
| safe_browsing_opt_in == EXTENDED_REPORTING_ONLY || |
| safe_browsing_opt_in == SAFE_BROWSING_AND_EXTENDED_REPORTING); |
| if (incidents_sent) |
| prefs->Set(prefs::kSafeBrowsingIncidentsSent, *incidents_sent); |
| |
| // Remember whether or not to create an incident. |
| profile_properties_[profile_name].on_addition_action = on_addition_action; |
| |
| // Boom (or fizzle). |
| return profile_manager_.CreateTestingProfile( |
| profile_name, std::move(prefs), base::ASCIIToUTF16(profile_name), |
| 0, // avatar_id (unused) |
| std::string(), // supervised_user_id (unused) |
| TestingProfile::TestingFactories()); |
| } |
| |
| // Configures a callback to run when the next upload is started that will post |
| // a task to delete the profile. This task will run before the upload |
| // finishes. |
| void DeleteProfileOnUpload(Profile* profile) { |
| ASSERT_TRUE(on_start_upload_callback_.is_null()); |
| on_start_upload_callback_ = |
| base::Bind(&IncidentReportingServiceTest::DelayedDeleteProfile, |
| base::Unretained(this), |
| profile); |
| } |
| |
| // Returns an incident suitable for testing. |
| std::unique_ptr<safe_browsing::Incident> MakeTestIncident(const char* value) { |
| std::unique_ptr< |
| safe_browsing:: |
| ClientIncidentReport_IncidentData_TrackedPreferenceIncident> |
| incident( |
| new safe_browsing:: |
| ClientIncidentReport_IncidentData_TrackedPreferenceIncident()); |
| incident->set_path(kTestTrackedPrefPath); |
| if (value) |
| incident->set_atomic_value(value); |
| return std::make_unique<safe_browsing::TrackedPreferenceIncident>( |
| std::move(incident), false /* is_personal */); |
| } |
| |
| // Adds a test incident to the service. |
| void AddTestIncident(Profile* profile) { |
| std::unique_ptr<safe_browsing::IncidentReceiver> receiver( |
| instance_->GetIncidentReceiver()); |
| if (profile) |
| receiver->AddIncidentForProfile(profile, MakeTestIncident(nullptr)); |
| else |
| receiver->AddIncidentForProcess(MakeTestIncident(nullptr)); |
| } |
| |
| // Registers the callback to be run for delayed analysis. |
| void RegisterAnalysis(OnDelayedAnalysisAction on_delayed_analysis_action) { |
| on_delayed_analysis_action_ = on_delayed_analysis_action; |
| instance_->RegisterDelayedAnalysisCallback( |
| base::Bind(&IncidentReportingServiceTest::OnDelayedAnalysis, |
| base::Unretained(this))); |
| } |
| |
| // Expects that |incident_count| incidents were uploaded by the service with |
| // the described downloads, then clears the instance for subsequent incidents. |
| void ExpectTestIncidentUploadWithBinaryDownload(int incident_count); |
| void ExpectTestIncidentUploadWithNonBinaryDownload(int incident_count); |
| void ExpectTestIncidentUploadWithBothDownloads(int incident_count); |
| |
| void AssertNoUpload() { ASSERT_FALSE(uploaded_report_); } |
| |
| bool HasCollectedEnvironmentAndExtensionData() const { |
| return environment_collected_ && instance_->HasCollectedExtension(); |
| } |
| bool HasCreatedDownloadFinder() const { return download_finder_created_; } |
| bool DownloadFinderDestroyed() const { return download_finder_destroyed_; } |
| bool UploaderDestroyed() const { return uploader_destroyed_; } |
| bool DelayedAnalysisRan() const { return delayed_analysis_ran_; } |
| |
| // Fakes BrowserThreads and the main MessageLoop. |
| content::TestBrowserThreadBundle thread_bundle_; |
| |
| // Replaces the main MessageLoop's TaskRunner with a TaskRunner on which time |
| // is mocked to allow testing of things bound to timers below. |
| base::ScopedMockTimeMessageLoopTaskRunner mock_time_task_runner_; |
| |
| extensions::QuotaService::ScopedDisablePurgeForTesting |
| disable_purge_for_testing_; |
| TestingProfileManager profile_manager_; |
| std::unique_ptr<TestIncidentReportingService> instance_; |
| base::Closure on_start_upload_callback_; |
| OnCreateDownloadFinderAction on_create_download_finder_action_; |
| OnDelayedAnalysisAction on_delayed_analysis_action_; |
| safe_browsing::IncidentReportUploader::Result upload_result_; |
| bool environment_collected_; |
| bool download_finder_created_; |
| std::unique_ptr<safe_browsing::ClientIncidentReport> uploaded_report_; |
| bool download_finder_destroyed_; |
| bool uploader_destroyed_; |
| bool delayed_analysis_ran_; |
| |
| private: |
| // A fake IncidentReportUploader that posts a task to provide a given response |
| // back to the incident reporting service. It also reports back to the test |
| // harness via a closure when it is deleted by the incident reporting service. |
| class FakeUploader : public safe_browsing::IncidentReportUploader { |
| public: |
| FakeUploader( |
| const base::Closure& on_deleted, |
| const safe_browsing::IncidentReportUploader::OnResultCallback& callback, |
| safe_browsing::IncidentReportUploader::Result result) |
| : safe_browsing::IncidentReportUploader(callback), |
| on_deleted_(on_deleted), |
| result_(result) { |
| // Post a task that will provide the response. |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&FakeUploader::FinishUpload, base::Unretained(this))); |
| } |
| ~FakeUploader() override { on_deleted_.Run(); } |
| |
| private: |
| void FinishUpload() { |
| // Callbacks have a tendency to delete the uploader, so no touching |
| // anything after this. |
| callback_.Run(result_, |
| std::unique_ptr<safe_browsing::ClientIncidentResponse>()); |
| } |
| |
| base::Closure on_deleted_; |
| safe_browsing::IncidentReportUploader::Result result_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeUploader); |
| }; |
| |
| class FakeDownloadFinder : public safe_browsing::LastDownloadFinder { |
| public: |
| static std::unique_ptr<safe_browsing::LastDownloadFinder> Create( |
| const base::Closure& on_deleted, |
| std::unique_ptr<safe_browsing::ClientIncidentReport_DownloadDetails> |
| binary_download, |
| std::unique_ptr< |
| safe_browsing::ClientIncidentReport_NonBinaryDownloadDetails> |
| non_binary_download, |
| const safe_browsing::LastDownloadFinder::LastDownloadCallback& |
| callback) { |
| // Post a task to run the callback. |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(callback, std::move(binary_download), |
| std::move(non_binary_download))); |
| return std::unique_ptr<safe_browsing::LastDownloadFinder>( |
| new FakeDownloadFinder(on_deleted)); |
| } |
| |
| ~FakeDownloadFinder() override { on_deleted_.Run(); } |
| |
| private: |
| explicit FakeDownloadFinder(const base::Closure& on_deleted) |
| : on_deleted_(on_deleted) {} |
| |
| base::Closure on_deleted_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeDownloadFinder); |
| }; |
| |
| // Confirms that the test incident(s) was/were uploaded by the service, then |
| // clears the instance for subsequent incidents. |
| void ExpectTestIncidentUploadedImpl(int incident_count, |
| bool withBinaryDownload, |
| bool withNonBinaryDownload) { |
| if (incident_count == 0) { |
| ASSERT_FALSE(uploaded_report_); |
| return; |
| } |
| ASSERT_TRUE(uploaded_report_); |
| ASSERT_EQ(incident_count, uploaded_report_->incident_size()); |
| for (int i = 0; i < incident_count; ++i) { |
| ASSERT_TRUE(uploaded_report_->incident(i).has_incident_time_msec()); |
| ASSERT_NE(0LL, uploaded_report_->incident(i).incident_time_msec()); |
| ASSERT_TRUE(uploaded_report_->incident(i).has_tracked_preference()); |
| ASSERT_TRUE( |
| uploaded_report_->incident(i).tracked_preference().has_path()); |
| ASSERT_EQ(std::string(kTestTrackedPrefPath), |
| uploaded_report_->incident(i).tracked_preference().path()); |
| } |
| ASSERT_TRUE(uploaded_report_->has_environment()); |
| ASSERT_TRUE(uploaded_report_->environment().has_os()); |
| ASSERT_TRUE(uploaded_report_->environment().os().has_os_name()); |
| ASSERT_EQ(std::string(kFakeOsName), |
| uploaded_report_->environment().os().os_name()); |
| ASSERT_EQ( |
| std::string(kFakeExtensionId), |
| uploaded_report_->extension_data().last_installed_extension().id()); |
| |
| if (withBinaryDownload) { |
| ASSERT_EQ(std::string(kFakeDownloadToken), |
| uploaded_report_->download().token()); |
| } |
| if (withNonBinaryDownload) { |
| ASSERT_EQ(std::string(kFakeDownloadHost), |
| uploaded_report_->non_binary_download().host()); |
| } |
| |
| uploaded_report_.reset(); |
| } |
| |
| // Properties for a profile that impact the behavior of the test. |
| struct ProfileProperties { |
| ProfileProperties() : on_addition_action(ON_PROFILE_ADDITION_NO_ACTION) {} |
| |
| // The action taken by the test fixture during profile initialization |
| // (before NOTIFICATION_PROFILE_ADDED is sent). |
| OnProfileAdditionAction on_addition_action; |
| }; |
| |
| // Posts a task to delete the profile. |
| void DelayedDeleteProfile(Profile* profile) { |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(&TestingProfileManager::DeleteTestingProfile, |
| base::Unretained(&profile_manager_), |
| profile->GetProfileUserName())); |
| } |
| |
| // A callback run by the test fixture when a profile is added. An incident |
| // is added. |
| void PreProfileAdd(Profile* profile) { |
| // The instance must have already been created. |
| ASSERT_TRUE(instance_); |
| // Add a test incident to the service if requested. |
| OnProfileAdditionAction action = |
| profile_properties_[profile->GetProfileUserName()].on_addition_action; |
| switch (action) { |
| case ON_PROFILE_ADDITION_ADD_INCIDENT: |
| AddTestIncident(profile); |
| break; |
| case ON_PROFILE_ADDITION_ADD_TWO_INCIDENTS: |
| AddTestIncident(profile); |
| AddTestIncident(profile); |
| break; |
| default: |
| ASSERT_EQ(ON_PROFILE_ADDITION_NO_ACTION, action); |
| break; |
| } |
| } |
| |
| // A fake CollectEnvironmentData implementation invoked by the service during |
| // operation. |
| void CollectEnvironmentData( |
| safe_browsing::ClientIncidentReport_EnvironmentData* data) { |
| ASSERT_TRUE(data); |
| data->mutable_os()->set_os_name(kFakeOsName); |
| environment_collected_ = true; |
| } |
| |
| // A fake CreateDownloadFinder implementation invoked by the service during |
| // operation. |
| std::unique_ptr<safe_browsing::LastDownloadFinder> CreateDownloadFinder( |
| const safe_browsing::LastDownloadFinder::LastDownloadCallback& callback) { |
| download_finder_created_ = true; |
| std::unique_ptr<safe_browsing::ClientIncidentReport_DownloadDetails> |
| binary_download; |
| std::unique_ptr< |
| safe_browsing::ClientIncidentReport_NonBinaryDownloadDetails> |
| non_binary_download; |
| if (on_create_download_finder_action_ == |
| ON_CREATE_DOWNLOAD_FINDER_NO_PROFILES) { |
| return std::unique_ptr<safe_browsing::LastDownloadFinder>(); |
| } |
| if (on_create_download_finder_action_ == |
| ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND || |
| on_create_download_finder_action_ == |
| ON_CREATE_DOWNLOAD_FINDER_BINARY_DOWNLOAD_FOUND) { |
| binary_download.reset( |
| new safe_browsing::ClientIncidentReport_DownloadDetails); |
| binary_download->set_token(kFakeDownloadToken); |
| } |
| if (on_create_download_finder_action_ == |
| ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND || |
| on_create_download_finder_action_ == |
| ON_CREATE_DOWNLOAD_FINDER_NON_BINARY_DOWNLOAD_FOUND) { |
| non_binary_download.reset( |
| new safe_browsing::ClientIncidentReport_NonBinaryDownloadDetails); |
| non_binary_download->set_host(kFakeDownloadHost); |
| } |
| |
| return std::unique_ptr<safe_browsing::LastDownloadFinder>( |
| FakeDownloadFinder::Create( |
| base::Bind(&IncidentReportingServiceTest::OnDownloadFinderDestroyed, |
| base::Unretained(this)), |
| std::move(binary_download), std::move(non_binary_download), |
| callback)); |
| } |
| |
| // A fake StartUpload implementation invoked by the service during operation. |
| std::unique_ptr<safe_browsing::IncidentReportUploader> StartUpload( |
| const safe_browsing::IncidentReportUploader::OnResultCallback& callback, |
| const safe_browsing::ClientIncidentReport& report) { |
| // Remember the report that is being uploaded. |
| uploaded_report_.reset(new safe_browsing::ClientIncidentReport(report)); |
| // Run and clear the OnStartUpload callback, if provided. |
| if (!on_start_upload_callback_.is_null()) { |
| on_start_upload_callback_.Run(); |
| on_start_upload_callback_ = base::Closure(); |
| } |
| return std::make_unique<FakeUploader>( |
| base::Bind(&IncidentReportingServiceTest::OnUploaderDestroyed, |
| base::Unretained(this)), |
| callback, upload_result_); |
| } |
| |
| void OnDownloadFinderDestroyed() { download_finder_destroyed_ = true; } |
| void OnUploaderDestroyed() { uploader_destroyed_ = true; } |
| |
| void OnDelayedAnalysis( |
| std::unique_ptr<safe_browsing::IncidentReceiver> receiver) { |
| delayed_analysis_ran_ = true; |
| if (on_delayed_analysis_action_ == ON_DELAYED_ANALYSIS_ADD_INCIDENT) |
| receiver->AddIncidentForProcess(MakeTestIncident(nullptr)); |
| } |
| |
| #if defined(OS_WIN) |
| registry_util::RegistryOverrideManager registry_override_manager_; |
| #endif |
| |
| // A mapping of profile name to its corresponding properties. |
| std::map<std::string, ProfileProperties> profile_properties_; |
| |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| // static |
| base::LazyInstance<base::ThreadLocalPointer< |
| IncidentReportingServiceTest::TestIncidentReportingService> >::Leaky |
| IncidentReportingServiceTest::TestIncidentReportingService::test_instance_ = |
| LAZY_INSTANCE_INITIALIZER; |
| |
| void IncidentReportingServiceTest::ExpectTestIncidentUploadWithBinaryDownload( |
| int incident_count) { |
| ExpectTestIncidentUploadedImpl(incident_count, true, false); |
| } |
| |
| void IncidentReportingServiceTest:: |
| ExpectTestIncidentUploadWithNonBinaryDownload(int incident_count) { |
| ExpectTestIncidentUploadedImpl(incident_count, false, true); |
| } |
| |
| void IncidentReportingServiceTest::ExpectTestIncidentUploadWithBothDownloads( |
| int incident_count) { |
| ExpectTestIncidentUploadedImpl(incident_count, true, false); |
| } |
| |
| const char IncidentReportingServiceTest::kFakeOsName[] = "fakedows"; |
| const char IncidentReportingServiceTest::kFakeDownloadToken[] = "fakedlt"; |
| const char IncidentReportingServiceTest::kFakeDownloadHost[] = "chromium.org"; |
| const char IncidentReportingServiceTest::kTestTrackedPrefPath[] = "some_pref"; |
| const char IncidentReportingServiceTest::kFakeExtensionId[] = "fakeExtensionId"; |
| |
| // Tests that an incident added during profile initialization when safe browsing |
| // extended reporting is on is uploaded. |
| TEST_F(IncidentReportingServiceTest, AddIncident) { |
| CreateIncidentReportingService(); |
| |
| // Create the profile, thereby causing the test to begin. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that environment and extension collection took place. |
| EXPECT_TRUE(HasCollectedEnvironmentAndExtensionData()); |
| |
| // Verify that the most recent download was looked for. |
| EXPECT_TRUE(HasCreatedDownloadFinder()); |
| |
| // Verify that report upload took place and contained the incident, |
| // environment data, and download details. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Verify that the download finder and the uploader were destroyed. |
| ASSERT_TRUE(DownloadFinderDestroyed()); |
| ASSERT_TRUE(UploaderDestroyed()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that multiple incidents are coalesced into the same report. |
| TEST_F(IncidentReportingServiceTest, CoalesceIncidents) { |
| CreateIncidentReportingService(); |
| |
| // Create the profile, thereby causing the test to begin. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_TWO_INCIDENTS, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that environment and extension collection took place. |
| EXPECT_TRUE(HasCollectedEnvironmentAndExtensionData()); |
| |
| // Verify that the most recent download was looked for. |
| EXPECT_TRUE(HasCreatedDownloadFinder()); |
| |
| // Verify that report upload took place and contained the incident, |
| // environment data, and download details. |
| ExpectTestIncidentUploadWithBinaryDownload(2); |
| |
| // Verify that the download finder and the uploader were destroyed. |
| ASSERT_TRUE(DownloadFinderDestroyed()); |
| ASSERT_TRUE(UploaderDestroyed()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that an incident added during profile initialization when safe browsing |
| // is off is not uploaded. |
| TEST_F(IncidentReportingServiceTest, NoSafeBrowsing) { |
| CreateIncidentReportingService(); |
| // Create the profile, thereby causing the test to begin. |
| CreateProfile("profile1", EXTENDED_REPORTING_ONLY, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that no report upload took place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that incidents are only uploaded after a profile has been opted into |
| // extended reporting. |
| TEST_F(IncidentReportingServiceTest, NoUploadBeforeExtendedReporting) { |
| CreateIncidentReportingService(); |
| // Create the profile, thereby causing the test to begin. |
| Profile* profile = CreateProfile("profile1", SAFE_BROWSING_ONLY, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| std::unique_ptr<safe_browsing::IncidentReceiver> receiver( |
| instance_->GetIncidentReceiver()); |
| |
| // Add a process-wide test incident. |
| receiver->AddIncidentForProcess(MakeTestIncident(nullptr)); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Downloads and environment data should have not been collected |
| // (DownloadFinder will be created, but should be a no-op since no eligible |
| // profiles are loaded). |
| ASSERT_TRUE(HasCreatedDownloadFinder()); |
| ASSERT_FALSE(HasCollectedEnvironmentAndExtensionData()); |
| |
| // Verify that no report upload took place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| |
| safe_browsing::SetExtendedReportingPref(profile->GetPrefs(), true); |
| |
| // Add a variation on the incident to the service. |
| instance_->GetIncidentReceiver()->AddIncidentForProfile( |
| profile, MakeTestIncident("squids")); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that environment collection took place. |
| EXPECT_TRUE(HasCollectedEnvironmentAndExtensionData()); |
| |
| // Verify that the most recent download was looked for. |
| EXPECT_TRUE(HasCreatedDownloadFinder()); |
| |
| // Verify that a report upload took place, and only the second incident was |
| // uploaded. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that no incident report is uploaded if there is no recent download. |
| TEST_F(IncidentReportingServiceTest, NoDownloadNoUpload) { |
| CreateIncidentReportingService(); |
| // Tell the fixture to return no downloads found. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_NO_DOWNLOADS); |
| |
| // Create the profile, thereby causing the test to begin. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that the download finder was run but that no report upload took |
| // place. |
| EXPECT_TRUE(HasCreatedDownloadFinder()); |
| AssertNoUpload(); |
| EXPECT_TRUE(DownloadFinderDestroyed()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that two incidents of the same type with different payloads lead to an |
| // upload even if the first one is pruned. |
| TEST_F(IncidentReportingServiceTest, NoDownloadPrunedIncidentOneUpload) { |
| CreateIncidentReportingService(); |
| // Tell the fixture to return no downloads found. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_NO_DOWNLOADS); |
| |
| // Create the profile, thereby causing the test to begin. |
| Profile* profile = |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Assert that no report upload took place. |
| AssertNoUpload(); |
| |
| // Tell the fixture to return a download now. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND); |
| |
| // Add a variation on the incident to the service. |
| instance_->GetIncidentReceiver()->AddIncidentForProfile( |
| profile, MakeTestIncident("leeches")); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that an additional report upload took place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that an identical incident added after an incident is pruned due to not |
| // having a download does not lead to an upload. |
| TEST_F(IncidentReportingServiceTest, NoDownloadPrunedSameIncidentNoUpload) { |
| CreateIncidentReportingService(); |
| // Tell the fixture to return no downloads found. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_NO_DOWNLOADS); |
| |
| // Create the profile, thereby causing the test to begin. |
| Profile* profile = |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Assert that no report upload took place. |
| AssertNoUpload(); |
| |
| // Tell the fixture to return a download now. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND); |
| |
| // Add the incident to the service again. |
| AddTestIncident(profile); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that no additional report upload took place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that no incident report is uploaded if there is no recent download. |
| TEST_F(IncidentReportingServiceTest, NoProfilesNoUpload) { |
| CreateIncidentReportingService(); |
| // Tell the fixture to pretend there are no profiles eligible for finding |
| // downloads. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_NO_PROFILES); |
| |
| // Create the profile, thereby causing the test to begin. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that the download finder was run but that no report upload took |
| // place. |
| EXPECT_TRUE(HasCreatedDownloadFinder()); |
| AssertNoUpload(); |
| // Although CreateDownloadFinder was called, no instance was returned so there |
| // is nothing to have been destroyed. |
| EXPECT_FALSE(DownloadFinderDestroyed()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that an identical incident added after upload is not uploaded again. |
| TEST_F(IncidentReportingServiceTest, OneIncidentOneUpload) { |
| CreateIncidentReportingService(); |
| // Create the profile, thereby causing the test to begin. |
| Profile* profile = |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that report upload took place and contained the incident and |
| // environment data. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Add the incident to the service again. |
| AddTestIncident(profile); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that no additional report upload took place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that two incidents of the same type with different payloads lead to two |
| // uploads. |
| TEST_F(IncidentReportingServiceTest, TwoIncidentsTwoUploads) { |
| CreateIncidentReportingService(); |
| // Create the profile, thereby causing the test to begin. |
| Profile* profile = |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that report upload took place and contained the incident and |
| // environment data. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Add a variation on the incident to the service. |
| instance_->GetIncidentReceiver()->AddIncidentForProfile( |
| profile, MakeTestIncident("leeches")); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that an additional report upload took place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that the same incident added for two different profiles in sequence |
| // results in two uploads. |
| TEST_F(IncidentReportingServiceTest, TwoProfilesTwoUploads) { |
| CreateIncidentReportingService(); |
| // Create the profile, thereby causing the test to begin. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that report upload took place and contained the incident and |
| // environment data. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Create a second profile with its own incident on addition. |
| CreateProfile("profile2", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that a second report upload took place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that an upload succeeds if the profile is destroyed while it is |
| // pending. |
| TEST_F(IncidentReportingServiceTest, ProfileDestroyedDuringUpload) { |
| CreateIncidentReportingService(); |
| // Create a profile for which an incident will be added. |
| Profile* profile = |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_ADD_INCIDENT, nullptr); |
| |
| // Hook up a callback to run when the upload is started that will post a task |
| // to delete the profile. This task will run before the upload finishes. |
| DeleteProfileOnUpload(profile); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that report upload took place and contained the incident and |
| // environment data. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| |
| // The lack of a crash indicates that the deleted profile was not accessed by |
| // the service while handling the upload response. |
| } |
| |
| // Tests that no upload results from adding an incident that is not affiliated |
| // with a profile. |
| TEST_F(IncidentReportingServiceTest, ProcessWideNoProfileNoUpload) { |
| CreateIncidentReportingService(); |
| // Add the test incident. |
| AddTestIncident(nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // No upload should have taken place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that there is an upload when a profile is present for a proc-wide |
| // incident and that pruning works. |
| TEST_F(IncidentReportingServiceTest, ProcessWideOneUpload) { |
| CreateIncidentReportingService(); |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Add the test incident. |
| AddTestIncident(nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // An upload should have taken place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Add the incident to the service again. |
| AddTestIncident(nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that no additional report upload took place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that two process-wide incidents of the same type with different |
| // payloads added via the same callback lead to two uploads. |
| TEST_F(IncidentReportingServiceTest, ProcessWideTwoUploads) { |
| CreateIncidentReportingService(); |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Add the test incident. |
| std::unique_ptr<safe_browsing::IncidentReceiver> receiver( |
| instance_->GetIncidentReceiver()); |
| receiver->AddIncidentForProcess(MakeTestIncident(nullptr)); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // An upload should have taken place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Add a variation on the incident to the service. |
| receiver->AddIncidentForProcess(MakeTestIncident("leeches")); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that an additional report upload took place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that there is no upload when a profile appears after a proc-wide |
| // incident. |
| TEST_F(IncidentReportingServiceTest, ProcessWideNoUploadAfterProfile) { |
| CreateIncidentReportingService(); |
| // Add the test incident. |
| AddTestIncident(nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that no report upload took place. |
| AssertNoUpload(); |
| |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // No upload should have taken place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| TEST_F(IncidentReportingServiceTest, NoCollectionWithoutIncident) { |
| CreateIncidentReportingService(); |
| // Register a callback. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_NO_ACTION); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Confirm that the callback was not run. |
| ASSERT_FALSE(DelayedAnalysisRan()); |
| |
| // No collection should have taken place. |
| ASSERT_FALSE(HasCollectedEnvironmentAndExtensionData()); |
| |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Confirm that the callback was run. |
| ASSERT_TRUE(DelayedAnalysisRan()); |
| |
| // Still no collection should have taken place. |
| ASSERT_FALSE(HasCollectedEnvironmentAndExtensionData()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that delayed analysis callbacks are called following the addition of a |
| // profile that participates in safe browsing extended reporting. |
| TEST_F(IncidentReportingServiceTest, AnalysisAfterProfile) { |
| CreateIncidentReportingService(); |
| // Register a callback. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_NO_ACTION); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Not run yet. |
| ASSERT_FALSE(DelayedAnalysisRan()); |
| |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // And now they have. |
| ASSERT_TRUE(DelayedAnalysisRan()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that delayed analysis callbacks are called following their registration |
| // when a profile that participates in safe browsing extended reporting is |
| // already present. |
| TEST_F(IncidentReportingServiceTest, AnalysisWhenRegisteredWithProfile) { |
| CreateIncidentReportingService(); |
| // Add a profile that participates in safe browsing. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Register a callback. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_NO_ACTION); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Confirm that the callbacks were run. |
| ASSERT_TRUE(DelayedAnalysisRan()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that no upload results from a delayed analysis incident when no |
| // safe browsing extended reporting profile is present. |
| TEST_F(IncidentReportingServiceTest, DelayedAnalysisNoProfileNoUpload) { |
| CreateIncidentReportingService(); |
| // Register a callback that will add an incident. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_ADD_INCIDENT); |
| |
| // Add a profile that does not participate in safe browsing extended |
| // reporting. |
| CreateProfile("profile1", SAFE_BROWSING_ONLY, ON_PROFILE_ADDITION_NO_ACTION, |
| nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // The callback should not have been run. |
| ASSERT_FALSE(DelayedAnalysisRan()); |
| |
| // No upload should have taken place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that there is an upload when a profile is present for a delayed |
| // analysis incident and that pruning works. |
| TEST_F(IncidentReportingServiceTest, DelayedAnalysisOneUpload) { |
| CreateIncidentReportingService(); |
| // Register a callback that will add an incident. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_ADD_INCIDENT); |
| |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // The callback should have been run. |
| ASSERT_TRUE(DelayedAnalysisRan()); |
| |
| // An upload should have taken place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Add the incident to the service again. |
| AddTestIncident(nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that no additional report upload took place. |
| AssertNoUpload(); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that the service stops processing when no download is found. |
| TEST_F(IncidentReportingServiceTest, NoDownloadNoWaiting) { |
| CreateIncidentReportingService(); |
| // Tell the fixture to return no downloads found. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_NO_DOWNLOADS); |
| |
| // Register a callback. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_NO_ACTION); |
| |
| // Add a profile that participates in safe browsing extended reporting. |
| Profile* profile = |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Add an incident. |
| AddTestIncident(profile); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Verify that the download finder was run but that no report upload took |
| // place. |
| EXPECT_TRUE(HasCreatedDownloadFinder()); |
| AssertNoUpload(); |
| EXPECT_TRUE(DownloadFinderDestroyed()); |
| |
| // Ensure that the report is dropped. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that the service sends the report if a non-binary download is found. |
| TEST_F(IncidentReportingServiceTest, NonBinaryDownloadStillUploads) { |
| CreateIncidentReportingService(); |
| // Tell the fixture to return only the last non-binary download. |
| SetCreateDownloadFinderAction( |
| ON_CREATE_DOWNLOAD_FINDER_NON_BINARY_DOWNLOAD_FOUND); |
| |
| // Register a callback. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_ADD_INCIDENT); |
| |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Confirm that the callbacks were run. |
| ASSERT_TRUE(DelayedAnalysisRan()); |
| |
| // Verify that a report upload took place. |
| ExpectTestIncidentUploadWithNonBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Tests that the service can send both a binary and non-binary download. |
| TEST_F(IncidentReportingServiceTest, UploadsWithBothDownloadTypes) { |
| CreateIncidentReportingService(); |
| // Tell the fixture to return only the last non-binary download. |
| SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND); |
| |
| // Register a callback. |
| RegisterAnalysis(ON_DELAYED_ANALYSIS_ADD_INCIDENT); |
| |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // Confirm that the callbacks were run. |
| ASSERT_TRUE(DelayedAnalysisRan()); |
| |
| // Verify that a report upload took place. |
| ExpectTestIncidentUploadWithBothDownloads(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Test that a profile's prune state is properly cleaned upon load. |
| TEST_F(IncidentReportingServiceTest, CleanLegacyPruneState) { |
| CreateIncidentReportingService(); |
| const std::string blacklist_load_type(base::NumberToString( |
| static_cast<int>(safe_browsing::IncidentType::OBSOLETE_BLACKLIST_LOAD))); |
| const std::string preference_type(base::NumberToString( |
| static_cast<int>(safe_browsing::IncidentType::TRACKED_PREFERENCE))); |
| |
| // Set up a prune state dict with data to be cleared (and not). |
| std::unique_ptr<base::DictionaryValue> incidents_sent( |
| new base::DictionaryValue()); |
| auto type_dict = std::make_unique<base::DictionaryValue>(); |
| type_dict->SetKey("foo", base::Value("47")); |
| incidents_sent->SetWithoutPathExpansion(blacklist_load_type, |
| std::move(type_dict)); |
| type_dict = std::make_unique<base::DictionaryValue>(); |
| type_dict->SetKey("bar", base::Value("43")); |
| incidents_sent->SetWithoutPathExpansion(preference_type, |
| std::move(type_dict)); |
| |
| // Add a profile. |
| Profile* profile = |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, std::move(incidents_sent)); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| const base::DictionaryValue* new_state = |
| profile->GetPrefs()->GetDictionary(prefs::kSafeBrowsingIncidentsSent); |
| // The legacy value must be gone. |
| ASSERT_FALSE(new_state->HasKey(blacklist_load_type)); |
| // But other data must be untouched. |
| ASSERT_TRUE(new_state->HasKey(preference_type)); |
| } |
| |
| // Tests that an identical incident added after an incident is pruned and |
| // cleared leads to an upload. |
| TEST_F(IncidentReportingServiceTest, ProcessWideUploadClearUpload) { |
| CreateIncidentReportingService(); |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| std::unique_ptr<safe_browsing::IncidentReceiver> receiver( |
| instance_->GetIncidentReceiver()); |
| |
| // Add the test incident. |
| receiver->AddIncidentForProcess(MakeTestIncident(nullptr)); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // An upload should have taken place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Clear incident data. |
| receiver->ClearIncidentForProcess(MakeTestIncident(nullptr)); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // No uploads should have taken place. |
| ExpectTestIncidentUploadWithBinaryDownload(0); |
| |
| // Add the incident to the service again. |
| receiver->AddIncidentForProcess(MakeTestIncident(nullptr)); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // An upload should have taken place. |
| ExpectTestIncidentUploadWithBinaryDownload(1); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| TEST_F(IncidentReportingServiceTest, ClearProcessIncidentOnCleanState) { |
| CreateIncidentReportingService(); |
| // Add a profile that participates in safe browsing extended reporting. |
| CreateProfile("profile1", SAFE_BROWSING_AND_EXTENDED_REPORTING, |
| ON_PROFILE_ADDITION_NO_ACTION, nullptr); |
| |
| std::unique_ptr<safe_browsing::IncidentReceiver> receiver( |
| instance_->GetIncidentReceiver()); |
| |
| // Clear incident data. |
| receiver->ClearIncidentForProcess(MakeTestIncident(nullptr)); |
| |
| // Let all tasks run. |
| mock_time_task_runner_->FastForwardUntilNoTasksRemain(); |
| |
| // No uploads should have taken place. |
| ExpectTestIncidentUploadWithBinaryDownload(0); |
| |
| // Downloads and environment data should have not been collected. |
| ASSERT_FALSE(HasCreatedDownloadFinder()); |
| ASSERT_FALSE(HasCollectedEnvironmentAndExtensionData()); |
| |
| // Ensure that no report processing remains. |
| ASSERT_FALSE(instance_->IsProcessingReport()); |
| } |
| |
| // Parallel uploads |
| // Shutdown during processing |
| // environment colection taking longer than incident delay timer |
| // environment colection taking longer than incident delay timer, and then |
| // another incident arriving |