| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/safe_browsing/incident_reporting_service.h" | |
| 6 | |
| 7 #include <map> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/callback.h" | |
| 12 #include "base/lazy_instance.h" | |
| 13 #include "base/strings/utf_string_conversions.h" | |
| 14 #include "base/test/test_simple_task_runner.h" | |
| 15 #include "base/thread_task_runner_handle.h" | |
| 16 #include "base/threading/thread_local.h" | |
| 17 #include "chrome/browser/prefs/browser_prefs.h" | |
| 18 #include "chrome/browser/safe_browsing/incident_report_uploader.h" | |
| 19 #include "chrome/browser/safe_browsing/last_download_finder.h" | |
| 20 #include "chrome/common/pref_names.h" | |
| 21 #include "chrome/common/safe_browsing/csd.pb.h" | |
| 22 #include "chrome/test/base/testing_browser_process.h" | |
| 23 #include "chrome/test/base/testing_pref_service_syncable.h" | |
| 24 #include "chrome/test/base/testing_profile.h" | |
| 25 #include "chrome/test/base/testing_profile_manager.h" | |
| 26 #include "net/url_request/url_request_context_getter.h" | |
| 27 #include "testing/gtest/include/gtest/gtest.h" | |
| 28 | |
| 29 // A test fixture that sets up a test task runner and makes it the thread's | |
| 30 // runner. The fixture implements a fake envrionment data collector and a fake | |
| 31 // report uploader. | |
| 32 class IncidentReportingServiceTest : public testing::Test { | |
| 33 protected: | |
| 34 // An IRS class that allows a test harness to provide a fake environment | |
| 35 // collector and report uploader via callbacks. | |
| 36 class TestIncidentReportingService | |
| 37 : public safe_browsing::IncidentReportingService { | |
| 38 public: | |
| 39 typedef base::Callback<void(Profile*)> PreProfileAddCallback; | |
| 40 | |
| 41 typedef base::Callback< | |
| 42 void(safe_browsing::ClientIncidentReport_EnvironmentData*)> | |
| 43 CollectEnvironmentCallback; | |
| 44 | |
| 45 typedef base::Callback<scoped_ptr<safe_browsing::LastDownloadFinder>( | |
| 46 const safe_browsing::LastDownloadFinder::LastDownloadCallback& | |
| 47 callback)> CreateDownloadFinderCallback; | |
| 48 | |
| 49 typedef base::Callback<scoped_ptr<safe_browsing::IncidentReportUploader>( | |
| 50 const safe_browsing::IncidentReportUploader::OnResultCallback&, | |
| 51 const safe_browsing::ClientIncidentReport& report)> StartUploadCallback; | |
| 52 | |
| 53 TestIncidentReportingService( | |
| 54 const scoped_refptr<base::TaskRunner>& task_runner, | |
| 55 const PreProfileAddCallback& pre_profile_add_callback, | |
| 56 const CollectEnvironmentCallback& collect_environment_callback, | |
| 57 const CreateDownloadFinderCallback& create_download_finder_callback, | |
| 58 const StartUploadCallback& start_upload_callback) | |
| 59 : IncidentReportingService(NULL, | |
| 60 NULL, | |
| 61 base::TimeDelta::FromMilliseconds(5), | |
| 62 task_runner), | |
| 63 pre_profile_add_callback_(pre_profile_add_callback), | |
| 64 collect_environment_callback_(collect_environment_callback), | |
| 65 create_download_finder_callback_(create_download_finder_callback), | |
| 66 start_upload_callback_(start_upload_callback) { | |
| 67 SetCollectEnvironmentHook(&CollectEnvironmentData, task_runner); | |
| 68 test_instance_.Get().Set(this); | |
| 69 } | |
| 70 | |
| 71 virtual ~TestIncidentReportingService() { test_instance_.Get().Set(NULL); } | |
| 72 | |
| 73 protected: | |
| 74 virtual void OnProfileAdded(Profile* profile) OVERRIDE { | |
| 75 pre_profile_add_callback_.Run(profile); | |
| 76 safe_browsing::IncidentReportingService::OnProfileAdded(profile); | |
| 77 } | |
| 78 | |
| 79 virtual scoped_ptr<safe_browsing::LastDownloadFinder> CreateDownloadFinder( | |
| 80 const safe_browsing::LastDownloadFinder::LastDownloadCallback& callback) | |
| 81 OVERRIDE { | |
| 82 return create_download_finder_callback_.Run(callback); | |
| 83 } | |
| 84 | |
| 85 virtual scoped_ptr<safe_browsing::IncidentReportUploader> StartReportUpload( | |
| 86 const safe_browsing::IncidentReportUploader::OnResultCallback& callback, | |
| 87 const scoped_refptr<net::URLRequestContextGetter>& | |
| 88 request_context_getter, | |
| 89 const safe_browsing::ClientIncidentReport& report) OVERRIDE { | |
| 90 return start_upload_callback_.Run(callback, report); | |
| 91 } | |
| 92 | |
| 93 private: | |
| 94 static TestIncidentReportingService& current() { | |
| 95 return *test_instance_.Get().Get(); | |
| 96 } | |
| 97 | |
| 98 static void CollectEnvironmentData( | |
| 99 safe_browsing::ClientIncidentReport_EnvironmentData* data) { | |
| 100 current().collect_environment_callback_.Run(data); | |
| 101 }; | |
| 102 | |
| 103 static base::LazyInstance<base::ThreadLocalPointer< | |
| 104 TestIncidentReportingService> >::Leaky test_instance_; | |
| 105 | |
| 106 PreProfileAddCallback pre_profile_add_callback_; | |
| 107 CollectEnvironmentCallback collect_environment_callback_; | |
| 108 CreateDownloadFinderCallback create_download_finder_callback_; | |
| 109 StartUploadCallback start_upload_callback_; | |
| 110 }; | |
| 111 | |
| 112 // A type for specifying whether or not a profile created by CreateProfile | |
| 113 // participates in safe browsing. | |
| 114 enum SafeBrowsingDisposition { | |
| 115 SAFE_BROWSING_OPT_OUT, | |
| 116 SAFE_BROWSING_OPT_IN, | |
| 117 }; | |
| 118 | |
| 119 // A type for specifying the action to be taken by the test fixture during | |
| 120 // profile initialization (before NOTIFICATION_PROFILE_ADDED is sent). | |
| 121 enum OnProfileAdditionAction { | |
| 122 ON_PROFILE_ADDITION_NO_ACTION, | |
| 123 ON_PROFILE_ADDITION_ADD_INCIDENT, // Add an incident to the service. | |
| 124 ON_PROFILE_ADDITION_ADD_TWO_INCIDENTS, // Add two incidents to the service. | |
| 125 }; | |
| 126 | |
| 127 // A type for specifying the action to be taken by the test fixture when the | |
| 128 // service creates a LastDownloadFinder. | |
| 129 enum OnCreateDownloadFinderAction { | |
| 130 // Post a task that reports a download. | |
| 131 ON_CREATE_DOWNLOAD_FINDER_DOWNLOAD_FOUND, | |
| 132 // Post a task that reports no downloads found. | |
| 133 ON_CREATE_DOWNLOAD_FINDER_NO_DOWNLOADS, | |
| 134 // Immediately return due to a lack of eligible profiles. | |
| 135 ON_CREATE_DOWNLOAD_FINDER_NO_PROFILES, | |
| 136 }; | |
| 137 | |
| 138 // A type for specifying the action to be taken by the test fixture when its | |
| 139 // delayed analysis callback is run. | |
| 140 enum OnDelayedAnalysisAction { | |
| 141 ON_DELAYED_ANALYSIS_NO_ACTION, | |
| 142 ON_DELAYED_ANALYSIS_ADD_INCIDENT, // Add an incident to the service. | |
| 143 }; | |
| 144 | |
| 145 static const int64 kIncidentTimeMsec; | |
| 146 static const char kFakeOsName[]; | |
| 147 static const char kFakeDownloadToken[]; | |
| 148 static const char kTestTrackedPrefPath[]; | |
| 149 | |
| 150 IncidentReportingServiceTest() | |
| 151 : task_runner_(new base::TestSimpleTaskRunner), | |
| 152 thread_task_runner_handle_(task_runner_), | |
| 153 profile_manager_(TestingBrowserProcess::GetGlobal()), | |
| 154 instance_(new TestIncidentReportingService( | |
| 155 task_runner_, | |
| 156 base::Bind(&IncidentReportingServiceTest::PreProfileAdd, | |
| 157 base::Unretained(this)), | |
| 158 base::Bind(&IncidentReportingServiceTest::CollectEnvironmentData, | |
| 159 base::Unretained(this)), | |
| 160 base::Bind(&IncidentReportingServiceTest::CreateDownloadFinder, | |
| 161 base::Unretained(this)), | |
| 162 base::Bind(&IncidentReportingServiceTest::StartUpload, | |
| 163 base::Unretained(this)))), | |
| 164 on_create_download_finder_action_( | |
| 165 ON_CREATE_DOWNLOAD_FINDER_DOWNLOAD_FOUND), | |
| 166 on_delayed_analysis_action_(ON_DELAYED_ANALYSIS_NO_ACTION), | |
| 167 upload_result_(safe_browsing::IncidentReportUploader::UPLOAD_SUCCESS), | |
| 168 environment_collected_(), | |
| 169 download_finder_created_(), | |
| 170 download_finder_destroyed_(), | |
| 171 uploader_destroyed_(), | |
| 172 delayed_analysis_ran_() {} | |
| 173 | |
| 174 virtual void SetUp() OVERRIDE { | |
| 175 testing::Test::SetUp(); | |
| 176 ASSERT_TRUE(profile_manager_.SetUp()); | |
| 177 } | |
| 178 | |
| 179 // Sets the action to be taken by the test fixture when the service creates a | |
| 180 // LastDownloadFinder. | |
| 181 void SetCreateDownloadFinderAction(OnCreateDownloadFinderAction action) { | |
| 182 on_create_download_finder_action_ = action; | |
| 183 } | |
| 184 | |
| 185 // Creates and returns a profile (owned by the profile manager) with or | |
| 186 // without safe browsing enabled. An incident will be created within | |
| 187 // PreProfileAdd if requested. | |
| 188 TestingProfile* CreateProfile(const std::string& profile_name, | |
| 189 SafeBrowsingDisposition safe_browsing_opt_in, | |
| 190 OnProfileAdditionAction on_addition_action) { | |
| 191 // Create prefs for the profile with safe browsing enabled or not. | |
| 192 scoped_ptr<TestingPrefServiceSyncable> prefs( | |
| 193 new TestingPrefServiceSyncable); | |
| 194 chrome::RegisterUserProfilePrefs(prefs->registry()); | |
| 195 prefs->SetBoolean(prefs::kSafeBrowsingEnabled, | |
| 196 safe_browsing_opt_in == SAFE_BROWSING_OPT_IN); | |
| 197 | |
| 198 // Remember whether or not to create an incident. | |
| 199 profile_properties_[profile_name].on_addition_action = on_addition_action; | |
| 200 | |
| 201 // Boom (or fizzle). | |
| 202 return profile_manager_.CreateTestingProfile( | |
| 203 profile_name, | |
| 204 prefs.PassAs<PrefServiceSyncable>(), | |
| 205 base::ASCIIToUTF16(profile_name), | |
| 206 0, // avatar_id (unused) | |
| 207 std::string(), // supervised_user_id (unused) | |
| 208 TestingProfile::TestingFactories()); | |
| 209 } | |
| 210 | |
| 211 // Configures a callback to run when the next upload is started that will post | |
| 212 // a task to delete the profile. This task will run before the upload | |
| 213 // finishes. | |
| 214 void DeleteProfileOnUpload(Profile* profile) { | |
| 215 ASSERT_TRUE(on_start_upload_callback_.is_null()); | |
| 216 on_start_upload_callback_ = | |
| 217 base::Bind(&IncidentReportingServiceTest::DelayedDeleteProfile, | |
| 218 base::Unretained(this), | |
| 219 profile); | |
| 220 } | |
| 221 | |
| 222 // Returns an incident suitable for testing. | |
| 223 scoped_ptr<safe_browsing::ClientIncidentReport_IncidentData> | |
| 224 MakeTestIncident() { | |
| 225 scoped_ptr<safe_browsing::ClientIncidentReport_IncidentData> incident( | |
| 226 new safe_browsing::ClientIncidentReport_IncidentData()); | |
| 227 incident->set_incident_time_msec(kIncidentTimeMsec); | |
| 228 safe_browsing::ClientIncidentReport_IncidentData_TrackedPreferenceIncident* | |
| 229 tp_incident = incident->mutable_tracked_preference(); | |
| 230 tp_incident->set_path(kTestTrackedPrefPath); | |
| 231 return incident.Pass(); | |
| 232 } | |
| 233 | |
| 234 // Adds a test incident to the service. | |
| 235 void AddTestIncident(Profile* profile) { | |
| 236 instance_->GetAddIncidentCallback(profile).Run(MakeTestIncident().Pass()); | |
| 237 } | |
| 238 | |
| 239 // Registers the callback to be run for delayed analysis. | |
| 240 void RegisterAnalysis(OnDelayedAnalysisAction on_delayed_analysis_action) { | |
| 241 on_delayed_analysis_action_ = on_delayed_analysis_action; | |
| 242 instance_->RegisterDelayedAnalysisCallback( | |
| 243 base::Bind(&IncidentReportingServiceTest::OnDelayedAnalysis, | |
| 244 base::Unretained(this))); | |
| 245 } | |
| 246 | |
| 247 // Confirms that the test incident(s) was/were uploaded by the service, then | |
| 248 // clears the instance for subsequent incidents. | |
| 249 void ExpectTestIncidentUploaded(int incident_count) { | |
| 250 ASSERT_TRUE(uploaded_report_); | |
| 251 ASSERT_EQ(incident_count, uploaded_report_->incident_size()); | |
| 252 for (int i = 0; i < incident_count; ++i) { | |
| 253 ASSERT_TRUE(uploaded_report_->incident(i).has_incident_time_msec()); | |
| 254 ASSERT_EQ(kIncidentTimeMsec, | |
| 255 uploaded_report_->incident(i).incident_time_msec()); | |
| 256 ASSERT_TRUE(uploaded_report_->incident(i).has_tracked_preference()); | |
| 257 ASSERT_TRUE( | |
| 258 uploaded_report_->incident(i).tracked_preference().has_path()); | |
| 259 ASSERT_EQ(std::string(kTestTrackedPrefPath), | |
| 260 uploaded_report_->incident(i).tracked_preference().path()); | |
| 261 } | |
| 262 ASSERT_TRUE(uploaded_report_->has_environment()); | |
| 263 ASSERT_TRUE(uploaded_report_->environment().has_os()); | |
| 264 ASSERT_TRUE(uploaded_report_->environment().os().has_os_name()); | |
| 265 ASSERT_EQ(std::string(kFakeOsName), | |
| 266 uploaded_report_->environment().os().os_name()); | |
| 267 ASSERT_EQ(std::string(kFakeDownloadToken), | |
| 268 uploaded_report_->download().token()); | |
| 269 | |
| 270 uploaded_report_.reset(); | |
| 271 } | |
| 272 | |
| 273 void AssertNoUpload() { ASSERT_FALSE(uploaded_report_); } | |
| 274 | |
| 275 bool HasCollectedEnvironmentData() const { return environment_collected_; } | |
| 276 bool HasCreatedDownloadFinder() const { return download_finder_created_; } | |
| 277 bool DownloadFinderDestroyed() const { return download_finder_destroyed_; } | |
| 278 bool UploaderDestroyed() const { return uploader_destroyed_; } | |
| 279 bool DelayedAnalysisRan() const { return delayed_analysis_ran_; } | |
| 280 | |
| 281 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | |
| 282 base::ThreadTaskRunnerHandle thread_task_runner_handle_; | |
| 283 TestingProfileManager profile_manager_; | |
| 284 scoped_ptr<safe_browsing::IncidentReportingService> instance_; | |
| 285 base::Closure on_start_upload_callback_; | |
| 286 OnCreateDownloadFinderAction on_create_download_finder_action_; | |
| 287 OnDelayedAnalysisAction on_delayed_analysis_action_; | |
| 288 safe_browsing::IncidentReportUploader::Result upload_result_; | |
| 289 bool environment_collected_; | |
| 290 bool download_finder_created_; | |
| 291 scoped_ptr<safe_browsing::ClientIncidentReport> uploaded_report_; | |
| 292 bool download_finder_destroyed_; | |
| 293 bool uploader_destroyed_; | |
| 294 bool delayed_analysis_ran_; | |
| 295 | |
| 296 private: | |
| 297 // A fake IncidentReportUploader that posts a task to provide a given response | |
| 298 // back to the incident reporting service. It also reports back to the test | |
| 299 // harness via a closure when it is deleted by the incident reporting service. | |
| 300 class FakeUploader : public safe_browsing::IncidentReportUploader { | |
| 301 public: | |
| 302 FakeUploader( | |
| 303 const base::Closure& on_deleted, | |
| 304 const safe_browsing::IncidentReportUploader::OnResultCallback& callback, | |
| 305 safe_browsing::IncidentReportUploader::Result result) | |
| 306 : safe_browsing::IncidentReportUploader(callback), | |
| 307 on_deleted_(on_deleted), | |
| 308 result_(result) { | |
| 309 // Post a task that will provide the response. | |
| 310 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 311 FROM_HERE, | |
| 312 base::Bind(&FakeUploader::FinishUpload, base::Unretained(this))); | |
| 313 } | |
| 314 virtual ~FakeUploader() { on_deleted_.Run(); } | |
| 315 | |
| 316 private: | |
| 317 void FinishUpload() { | |
| 318 // Callbacks have a tendency to delete the uploader, so no touching | |
| 319 // anything after this. | |
| 320 callback_.Run(result_, | |
| 321 scoped_ptr<safe_browsing::ClientIncidentResponse>()); | |
| 322 } | |
| 323 | |
| 324 base::Closure on_deleted_; | |
| 325 safe_browsing::IncidentReportUploader::Result result_; | |
| 326 | |
| 327 DISALLOW_COPY_AND_ASSIGN(FakeUploader); | |
| 328 }; | |
| 329 | |
| 330 class FakeDownloadFinder : public safe_browsing::LastDownloadFinder { | |
| 331 public: | |
| 332 static scoped_ptr<safe_browsing::LastDownloadFinder> Create( | |
| 333 const base::Closure& on_deleted, | |
| 334 scoped_ptr<safe_browsing::ClientIncidentReport_DownloadDetails> | |
| 335 download, | |
| 336 const safe_browsing::LastDownloadFinder::LastDownloadCallback& | |
| 337 callback) { | |
| 338 // Post a task to run the callback. | |
| 339 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 340 FROM_HERE, base::Bind(callback, base::Passed(&download))); | |
| 341 return scoped_ptr<safe_browsing::LastDownloadFinder>( | |
| 342 new FakeDownloadFinder(on_deleted)); | |
| 343 } | |
| 344 | |
| 345 virtual ~FakeDownloadFinder() { on_deleted_.Run(); } | |
| 346 | |
| 347 private: | |
| 348 explicit FakeDownloadFinder(const base::Closure& on_deleted) | |
| 349 : on_deleted_(on_deleted) {} | |
| 350 | |
| 351 base::Closure on_deleted_; | |
| 352 | |
| 353 DISALLOW_COPY_AND_ASSIGN(FakeDownloadFinder); | |
| 354 }; | |
| 355 | |
| 356 // Properties for a profile that impact the behavior of the test. | |
| 357 struct ProfileProperties { | |
| 358 ProfileProperties() : on_addition_action(ON_PROFILE_ADDITION_NO_ACTION) {} | |
| 359 | |
| 360 // The action taken by the test fixture during profile initialization | |
| 361 // (before NOTIFICATION_PROFILE_ADDED is sent). | |
| 362 OnProfileAdditionAction on_addition_action; | |
| 363 }; | |
| 364 | |
| 365 // Returns the name of a profile as provided to CreateProfile. | |
| 366 static std::string GetProfileName(Profile* profile) { | |
| 367 // Cannot reliably use profile->GetProfileName() since the test needs the | |
| 368 // name before the profile manager sets it (which happens after profile | |
| 369 // addition). | |
| 370 return profile->GetPath().BaseName().AsUTF8Unsafe(); | |
| 371 } | |
| 372 | |
| 373 // Posts a task to delete the profile. | |
| 374 void DelayedDeleteProfile(Profile* profile) { | |
| 375 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 376 FROM_HERE, | |
| 377 base::Bind(&TestingProfileManager::DeleteTestingProfile, | |
| 378 base::Unretained(&profile_manager_), | |
| 379 GetProfileName(profile))); | |
| 380 } | |
| 381 | |
| 382 // A callback run by the test fixture when a profile is added. An incident | |
| 383 // is added. | |
| 384 void PreProfileAdd(Profile* profile) { | |
| 385 // The instance must have already been created. | |
| 386 ASSERT_TRUE(instance_); | |
| 387 // Add a test incident to the service if requested. | |
| 388 switch (profile_properties_[GetProfileName(profile)].on_addition_action) { | |
| 389 case ON_PROFILE_ADDITION_ADD_INCIDENT: | |
| 390 AddTestIncident(profile); | |
| 391 break; | |
| 392 case ON_PROFILE_ADDITION_ADD_TWO_INCIDENTS: | |
| 393 AddTestIncident(profile); | |
| 394 AddTestIncident(profile); | |
| 395 break; | |
| 396 default: | |
| 397 ASSERT_EQ( | |
| 398 ON_PROFILE_ADDITION_NO_ACTION, | |
| 399 profile_properties_[GetProfileName(profile)].on_addition_action); | |
| 400 break; | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 // A fake CollectEnvironmentData implementation invoked by the service during | |
| 405 // operation. | |
| 406 void CollectEnvironmentData( | |
| 407 safe_browsing::ClientIncidentReport_EnvironmentData* data) { | |
| 408 ASSERT_NE( | |
| 409 static_cast<safe_browsing::ClientIncidentReport_EnvironmentData*>(NULL), | |
| 410 data); | |
| 411 data->mutable_os()->set_os_name(kFakeOsName); | |
| 412 environment_collected_ = true; | |
| 413 } | |
| 414 | |
| 415 // A fake CreateDownloadFinder implementation invoked by the service during | |
| 416 // operation. | |
| 417 scoped_ptr<safe_browsing::LastDownloadFinder> CreateDownloadFinder( | |
| 418 const safe_browsing::LastDownloadFinder::LastDownloadCallback& callback) { | |
| 419 download_finder_created_ = true; | |
| 420 scoped_ptr<safe_browsing::ClientIncidentReport_DownloadDetails> download; | |
| 421 if (on_create_download_finder_action_ == | |
| 422 ON_CREATE_DOWNLOAD_FINDER_NO_PROFILES) { | |
| 423 return scoped_ptr<safe_browsing::LastDownloadFinder>(); | |
| 424 } | |
| 425 if (on_create_download_finder_action_ == | |
| 426 ON_CREATE_DOWNLOAD_FINDER_DOWNLOAD_FOUND) { | |
| 427 download.reset(new safe_browsing::ClientIncidentReport_DownloadDetails); | |
| 428 download->set_token(kFakeDownloadToken); | |
| 429 } | |
| 430 return scoped_ptr<safe_browsing::LastDownloadFinder>( | |
| 431 FakeDownloadFinder::Create( | |
| 432 base::Bind(&IncidentReportingServiceTest::OnDownloadFinderDestroyed, | |
| 433 base::Unretained(this)), | |
| 434 download.Pass(), | |
| 435 callback)); | |
| 436 } | |
| 437 | |
| 438 // A fake StartUpload implementation invoked by the service during operation. | |
| 439 scoped_ptr<safe_browsing::IncidentReportUploader> StartUpload( | |
| 440 const safe_browsing::IncidentReportUploader::OnResultCallback& callback, | |
| 441 const safe_browsing::ClientIncidentReport& report) { | |
| 442 // Remember the report that is being uploaded. | |
| 443 uploaded_report_.reset(new safe_browsing::ClientIncidentReport(report)); | |
| 444 // Run and clear the OnStartUpload callback, if provided. | |
| 445 if (!on_start_upload_callback_.is_null()) { | |
| 446 on_start_upload_callback_.Run(); | |
| 447 on_start_upload_callback_ = base::Closure(); | |
| 448 } | |
| 449 return scoped_ptr<safe_browsing::IncidentReportUploader>( | |
| 450 new FakeUploader( | |
| 451 base::Bind( | |
| 452 &IncidentReportingServiceTest::OnUploaderDestroyed, | |
| 453 base::Unretained(this)), | |
| 454 callback, | |
| 455 upload_result_)).Pass(); | |
| 456 } | |
| 457 | |
| 458 void OnDownloadFinderDestroyed() { download_finder_destroyed_ = true; } | |
| 459 void OnUploaderDestroyed() { uploader_destroyed_ = true; } | |
| 460 | |
| 461 void OnDelayedAnalysis(const safe_browsing::AddIncidentCallback& callback) { | |
| 462 delayed_analysis_ran_ = true; | |
| 463 if (on_delayed_analysis_action_ == ON_DELAYED_ANALYSIS_ADD_INCIDENT) | |
| 464 callback.Run(MakeTestIncident().Pass()); | |
| 465 } | |
| 466 | |
| 467 // A mapping of profile name to its corresponding properties. | |
| 468 std::map<std::string, ProfileProperties> profile_properties_; | |
| 469 }; | |
| 470 | |
| 471 // static | |
| 472 base::LazyInstance<base::ThreadLocalPointer< | |
| 473 IncidentReportingServiceTest::TestIncidentReportingService> >::Leaky | |
| 474 IncidentReportingServiceTest::TestIncidentReportingService::test_instance_ = | |
| 475 LAZY_INSTANCE_INITIALIZER; | |
| 476 | |
| 477 const int64 IncidentReportingServiceTest::kIncidentTimeMsec = 47LL; | |
| 478 const char IncidentReportingServiceTest::kFakeOsName[] = "fakedows"; | |
| 479 const char IncidentReportingServiceTest::kFakeDownloadToken[] = "fakedlt"; | |
| 480 const char IncidentReportingServiceTest::kTestTrackedPrefPath[] = "some_pref"; | |
| 481 | |
| 482 // Tests that an incident added during profile initialization when safe browsing | |
| 483 // is on is uploaded. | |
| 484 TEST_F(IncidentReportingServiceTest, AddIncident) { | |
| 485 CreateProfile( | |
| 486 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 487 | |
| 488 // Let all tasks run. | |
| 489 task_runner_->RunUntilIdle(); | |
| 490 | |
| 491 // Verify that environment collection took place. | |
| 492 EXPECT_TRUE(HasCollectedEnvironmentData()); | |
| 493 | |
| 494 // Verify that the most recent download was looked for. | |
| 495 EXPECT_TRUE(HasCreatedDownloadFinder()); | |
| 496 | |
| 497 // Verify that report upload took place and contained the incident, | |
| 498 // environment data, and download details. | |
| 499 ExpectTestIncidentUploaded(1); | |
| 500 | |
| 501 // Verify that the download finder and the uploader were destroyed. | |
| 502 ASSERT_TRUE(DownloadFinderDestroyed()); | |
| 503 ASSERT_TRUE(UploaderDestroyed()); | |
| 504 } | |
| 505 | |
| 506 // Tests that multiple incidents are coalesced into the same report. | |
| 507 TEST_F(IncidentReportingServiceTest, CoalesceIncidents) { | |
| 508 CreateProfile( | |
| 509 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_TWO_INCIDENTS); | |
| 510 | |
| 511 // Let all tasks run. | |
| 512 task_runner_->RunUntilIdle(); | |
| 513 | |
| 514 // Verify that environment collection took place. | |
| 515 EXPECT_TRUE(HasCollectedEnvironmentData()); | |
| 516 | |
| 517 // Verify that the most recent download was looked for. | |
| 518 EXPECT_TRUE(HasCreatedDownloadFinder()); | |
| 519 | |
| 520 // Verify that report upload took place and contained the incident, | |
| 521 // environment data, and download details. | |
| 522 ExpectTestIncidentUploaded(2); | |
| 523 | |
| 524 // Verify that the download finder and the uploader were destroyed. | |
| 525 ASSERT_TRUE(DownloadFinderDestroyed()); | |
| 526 ASSERT_TRUE(UploaderDestroyed()); | |
| 527 } | |
| 528 | |
| 529 // Tests that an incident added during profile initialization when safe browsing | |
| 530 // is off is not uploaded. | |
| 531 TEST_F(IncidentReportingServiceTest, NoSafeBrowsing) { | |
| 532 // Create the profile, thereby causing the test to begin. | |
| 533 CreateProfile( | |
| 534 "profile1", SAFE_BROWSING_OPT_OUT, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 535 | |
| 536 // Let all tasks run. | |
| 537 task_runner_->RunUntilIdle(); | |
| 538 | |
| 539 // Verify that no report upload took place. | |
| 540 AssertNoUpload(); | |
| 541 } | |
| 542 | |
| 543 // Tests that no incident report is uploaded if there is no recent download. | |
| 544 TEST_F(IncidentReportingServiceTest, NoDownloadNoUpload) { | |
| 545 // Tell the fixture to return no downloads found. | |
| 546 SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_NO_DOWNLOADS); | |
| 547 | |
| 548 // Create the profile, thereby causing the test to begin. | |
| 549 CreateProfile( | |
| 550 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 551 | |
| 552 // Let all tasks run. | |
| 553 task_runner_->RunUntilIdle(); | |
| 554 | |
| 555 // Verify that the download finder was run but that no report upload took | |
| 556 // place. | |
| 557 EXPECT_TRUE(HasCreatedDownloadFinder()); | |
| 558 AssertNoUpload(); | |
| 559 EXPECT_TRUE(DownloadFinderDestroyed()); | |
| 560 } | |
| 561 | |
| 562 // Tests that no incident report is uploaded if there is no recent download. | |
| 563 TEST_F(IncidentReportingServiceTest, NoProfilesNoUpload) { | |
| 564 // Tell the fixture to pretend there are no profiles eligible for finding | |
| 565 // downloads. | |
| 566 SetCreateDownloadFinderAction(ON_CREATE_DOWNLOAD_FINDER_NO_PROFILES); | |
| 567 | |
| 568 // Create the profile, thereby causing the test to begin. | |
| 569 CreateProfile( | |
| 570 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 571 | |
| 572 // Let all tasks run. | |
| 573 task_runner_->RunUntilIdle(); | |
| 574 | |
| 575 // Verify that the download finder was run but that no report upload took | |
| 576 // place. | |
| 577 EXPECT_TRUE(HasCreatedDownloadFinder()); | |
| 578 AssertNoUpload(); | |
| 579 // Although CreateDownloadFinder was called, no instance was returned so there | |
| 580 // is nothing to have been destroyed. | |
| 581 EXPECT_FALSE(DownloadFinderDestroyed()); | |
| 582 } | |
| 583 | |
| 584 // Tests that an identical incident added after upload is not uploaded again. | |
| 585 TEST_F(IncidentReportingServiceTest, OneIncidentOneUpload) { | |
| 586 // Create the profile, thereby causing the test to begin. | |
| 587 Profile* profile = CreateProfile( | |
| 588 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 589 | |
| 590 // Let all tasks run. | |
| 591 task_runner_->RunUntilIdle(); | |
| 592 | |
| 593 // Verify that report upload took place and contained the incident and | |
| 594 // environment data. | |
| 595 ExpectTestIncidentUploaded(1); | |
| 596 | |
| 597 // Add the incident to the service again. | |
| 598 AddTestIncident(profile); | |
| 599 | |
| 600 // Let all tasks run. | |
| 601 task_runner_->RunUntilIdle(); | |
| 602 | |
| 603 // Verify that no additional report upload took place. | |
| 604 AssertNoUpload(); | |
| 605 } | |
| 606 | |
| 607 // Tests that two incidents of the same type with different payloads lead to two | |
| 608 // uploads. | |
| 609 TEST_F(IncidentReportingServiceTest, TwoIncidentsTwoUploads) { | |
| 610 // Create the profile, thereby causing the test to begin. | |
| 611 Profile* profile = CreateProfile( | |
| 612 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 613 | |
| 614 // Let all tasks run. | |
| 615 task_runner_->RunUntilIdle(); | |
| 616 | |
| 617 // Verify that report upload took place and contained the incident and | |
| 618 // environment data. | |
| 619 ExpectTestIncidentUploaded(1); | |
| 620 | |
| 621 // Add a variation on the incident to the service. | |
| 622 scoped_ptr<safe_browsing::ClientIncidentReport_IncidentData> incident( | |
| 623 MakeTestIncident()); | |
| 624 incident->mutable_tracked_preference()->set_atomic_value("leeches"); | |
| 625 instance_->GetAddIncidentCallback(profile).Run(incident.Pass()); | |
| 626 | |
| 627 // Let all tasks run. | |
| 628 task_runner_->RunUntilIdle(); | |
| 629 | |
| 630 // Verify that an additional report upload took place. | |
| 631 ExpectTestIncidentUploaded(1); | |
| 632 } | |
| 633 | |
| 634 // Tests that the same incident added for two different profiles in sequence | |
| 635 // results in two uploads. | |
| 636 TEST_F(IncidentReportingServiceTest, TwoProfilesTwoUploads) { | |
| 637 // Create the profile, thereby causing the test to begin. | |
| 638 CreateProfile( | |
| 639 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 640 | |
| 641 // Let all tasks run. | |
| 642 task_runner_->RunUntilIdle(); | |
| 643 | |
| 644 // Verify that report upload took place and contained the incident and | |
| 645 // environment data. | |
| 646 ExpectTestIncidentUploaded(1); | |
| 647 | |
| 648 // Create a second profile with its own incident on addition. | |
| 649 CreateProfile( | |
| 650 "profile2", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 651 | |
| 652 // Let all tasks run. | |
| 653 task_runner_->RunUntilIdle(); | |
| 654 | |
| 655 // Verify that a second report upload took place. | |
| 656 ExpectTestIncidentUploaded(1); | |
| 657 } | |
| 658 | |
| 659 // Tests that an upload succeeds if the profile is destroyed while it is | |
| 660 // pending. | |
| 661 TEST_F(IncidentReportingServiceTest, ProfileDestroyedDuringUpload) { | |
| 662 // Create a profile for which an incident will be added. | |
| 663 Profile* profile = CreateProfile( | |
| 664 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_ADD_INCIDENT); | |
| 665 | |
| 666 // Hook up a callback to run when the upload is started that will post a task | |
| 667 // to delete the profile. This task will run before the upload finishes. | |
| 668 DeleteProfileOnUpload(profile); | |
| 669 | |
| 670 // Let all tasks run. | |
| 671 task_runner_->RunUntilIdle(); | |
| 672 | |
| 673 // Verify that report upload took place and contained the incident and | |
| 674 // environment data. | |
| 675 ExpectTestIncidentUploaded(1); | |
| 676 | |
| 677 // The lack of a crash indicates that the deleted profile was not accessed by | |
| 678 // the service while handling the upload response. | |
| 679 } | |
| 680 | |
| 681 // Tests that no upload takes place if the old pref was present. | |
| 682 TEST_F(IncidentReportingServiceTest, MigrateOldPref) { | |
| 683 Profile* profile = CreateProfile( | |
| 684 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_NO_ACTION); | |
| 685 | |
| 686 // This is a legacy profile. | |
| 687 profile->GetPrefs()->SetBoolean(prefs::kSafeBrowsingIncidentReportSent, true); | |
| 688 | |
| 689 // Add the test incident. | |
| 690 AddTestIncident(profile); | |
| 691 | |
| 692 // Let all tasks run. | |
| 693 task_runner_->RunUntilIdle(); | |
| 694 | |
| 695 // No upload should have taken place. | |
| 696 AssertNoUpload(); | |
| 697 | |
| 698 // The legacy pref should have been cleared. | |
| 699 ASSERT_FALSE( | |
| 700 profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingIncidentReportSent)); | |
| 701 | |
| 702 // Adding the same incident again should still result in no upload. | |
| 703 AddTestIncident(profile); | |
| 704 | |
| 705 // Let all tasks run. | |
| 706 task_runner_->RunUntilIdle(); | |
| 707 | |
| 708 // No upload should have taken place. | |
| 709 AssertNoUpload(); | |
| 710 } | |
| 711 | |
| 712 // Tests that no upload results from adding an incident that is not affiliated | |
| 713 // with a profile. | |
| 714 TEST_F(IncidentReportingServiceTest, ProcessWideNoProfileNoUpload) { | |
| 715 // Add the test incident. | |
| 716 AddTestIncident(NULL); | |
| 717 | |
| 718 // Let all tasks run. | |
| 719 task_runner_->RunUntilIdle(); | |
| 720 | |
| 721 // No upload should have taken place. | |
| 722 AssertNoUpload(); | |
| 723 } | |
| 724 | |
| 725 // Tests that there is an upload when a profile is present for a proc-wide | |
| 726 // incident and that pruning works. | |
| 727 TEST_F(IncidentReportingServiceTest, ProcessWideOneUpload) { | |
| 728 // Add a profile that participates in safe browsing. | |
| 729 CreateProfile( | |
| 730 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_NO_ACTION); | |
| 731 | |
| 732 // Add the test incident. | |
| 733 AddTestIncident(NULL); | |
| 734 | |
| 735 // Let all tasks run. | |
| 736 task_runner_->RunUntilIdle(); | |
| 737 | |
| 738 // An upload should have taken place. | |
| 739 ExpectTestIncidentUploaded(1); | |
| 740 | |
| 741 // Add the incident to the service again. | |
| 742 AddTestIncident(NULL); | |
| 743 | |
| 744 // Let all tasks run. | |
| 745 task_runner_->RunUntilIdle(); | |
| 746 | |
| 747 // Verify that no additional report upload took place. | |
| 748 AssertNoUpload(); | |
| 749 } | |
| 750 | |
| 751 // Tests that two process-wide incidents of the same type with different | |
| 752 // payloads added via the same callback lead to two uploads. | |
| 753 TEST_F(IncidentReportingServiceTest, ProcessWideTwoUploads) { | |
| 754 // Add a profile that participates in safe browsing. | |
| 755 CreateProfile( | |
| 756 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_NO_ACTION); | |
| 757 | |
| 758 // Add the test incident. | |
| 759 safe_browsing::AddIncidentCallback add_incident( | |
| 760 instance_->GetAddIncidentCallback(NULL)); | |
| 761 add_incident.Run(MakeTestIncident().Pass()); | |
| 762 | |
| 763 // Let all tasks run. | |
| 764 task_runner_->RunUntilIdle(); | |
| 765 | |
| 766 // An upload should have taken place. | |
| 767 ExpectTestIncidentUploaded(1); | |
| 768 | |
| 769 // Add a variation on the incident to the service. | |
| 770 scoped_ptr<safe_browsing::ClientIncidentReport_IncidentData> incident( | |
| 771 MakeTestIncident()); | |
| 772 incident->mutable_tracked_preference()->set_atomic_value("leeches"); | |
| 773 add_incident.Run(incident.Pass()); | |
| 774 | |
| 775 // Let all tasks run. | |
| 776 task_runner_->RunUntilIdle(); | |
| 777 | |
| 778 // Verify that an additional report upload took place. | |
| 779 ExpectTestIncidentUploaded(1); | |
| 780 } | |
| 781 | |
| 782 // Tests that there is an upload when a profile appears after a proc-wide | |
| 783 // incident. | |
| 784 TEST_F(IncidentReportingServiceTest, ProcessWideOneUploadAfterProfile) { | |
| 785 // Add the test incident. | |
| 786 AddTestIncident(NULL); | |
| 787 | |
| 788 // Let all tasks run. | |
| 789 task_runner_->RunUntilIdle(); | |
| 790 | |
| 791 // Verify that no report upload took place. | |
| 792 AssertNoUpload(); | |
| 793 | |
| 794 // Add a profile that participates in safe browsing. | |
| 795 CreateProfile( | |
| 796 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_NO_ACTION); | |
| 797 | |
| 798 // Let all tasks run. | |
| 799 task_runner_->RunUntilIdle(); | |
| 800 | |
| 801 // An upload should have taken place. | |
| 802 ExpectTestIncidentUploaded(1); | |
| 803 } | |
| 804 | |
| 805 // Tests that delayed analysis callbacks are called following the addition of a | |
| 806 // profile that participates in safe browsing. | |
| 807 TEST_F(IncidentReportingServiceTest, AnalysisAfterProfile) { | |
| 808 // Register a callback. | |
| 809 RegisterAnalysis(ON_DELAYED_ANALYSIS_NO_ACTION); | |
| 810 | |
| 811 // Let all tasks run. | |
| 812 task_runner_->RunUntilIdle(); | |
| 813 | |
| 814 // Not run yet. | |
| 815 ASSERT_FALSE(DelayedAnalysisRan()); | |
| 816 | |
| 817 // Add a profile that participates in safe browsing. | |
| 818 CreateProfile( | |
| 819 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_NO_ACTION); | |
| 820 | |
| 821 // Let all tasks run. | |
| 822 task_runner_->RunUntilIdle(); | |
| 823 | |
| 824 // And now they have. | |
| 825 ASSERT_TRUE(DelayedAnalysisRan()); | |
| 826 } | |
| 827 | |
| 828 // Tests that delayed analysis callbacks are called following their registration | |
| 829 // when a profile that participates in safe browsing is already present. | |
| 830 TEST_F(IncidentReportingServiceTest, AnalysisWhenRegisteredWithProfile) { | |
| 831 // Add a profile that participates in safe browsing. | |
| 832 CreateProfile( | |
| 833 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_NO_ACTION); | |
| 834 | |
| 835 // Register a callback. | |
| 836 RegisterAnalysis(ON_DELAYED_ANALYSIS_NO_ACTION); | |
| 837 | |
| 838 // Let all tasks run. | |
| 839 task_runner_->RunUntilIdle(); | |
| 840 | |
| 841 // Confirm that the callbacks were run. | |
| 842 ASSERT_TRUE(DelayedAnalysisRan()); | |
| 843 } | |
| 844 | |
| 845 // Tests that no upload results from a delayed analysis incident when no | |
| 846 // safe browsing profile is present. | |
| 847 TEST_F(IncidentReportingServiceTest, DelayedAnalysisNoProfileNoUpload) { | |
| 848 // Register a callback that will add an incident. | |
| 849 RegisterAnalysis(ON_DELAYED_ANALYSIS_ADD_INCIDENT); | |
| 850 | |
| 851 // Add a profile that does not participate in safe browsing. | |
| 852 CreateProfile( | |
| 853 "profile1", SAFE_BROWSING_OPT_OUT, ON_PROFILE_ADDITION_NO_ACTION); | |
| 854 | |
| 855 // Let all tasks run. | |
| 856 task_runner_->RunUntilIdle(); | |
| 857 | |
| 858 // The callback should not have been run. | |
| 859 ASSERT_FALSE(DelayedAnalysisRan()); | |
| 860 | |
| 861 // No upload should have taken place. | |
| 862 AssertNoUpload(); | |
| 863 } | |
| 864 | |
| 865 // Tests that there is an upload when a profile is present for a delayed | |
| 866 // analysis incident and that pruning works. | |
| 867 TEST_F(IncidentReportingServiceTest, DelayedAnalysisOneUpload) { | |
| 868 // Register a callback that will add an incident. | |
| 869 RegisterAnalysis(ON_DELAYED_ANALYSIS_ADD_INCIDENT); | |
| 870 | |
| 871 // Add a profile that participates in safe browsing. | |
| 872 CreateProfile( | |
| 873 "profile1", SAFE_BROWSING_OPT_IN, ON_PROFILE_ADDITION_NO_ACTION); | |
| 874 | |
| 875 // Let all tasks run. | |
| 876 task_runner_->RunUntilIdle(); | |
| 877 | |
| 878 // The callback should have been run. | |
| 879 ASSERT_TRUE(DelayedAnalysisRan()); | |
| 880 | |
| 881 // An upload should have taken place. | |
| 882 ExpectTestIncidentUploaded(1); | |
| 883 | |
| 884 // Add the incident to the service again. | |
| 885 AddTestIncident(NULL); | |
| 886 | |
| 887 // Let all tasks run. | |
| 888 task_runner_->RunUntilIdle(); | |
| 889 | |
| 890 // Verify that no additional report upload took place. | |
| 891 AssertNoUpload(); | |
| 892 } | |
| 893 | |
| 894 // Parallel uploads | |
| 895 // Shutdown during processing | |
| 896 // environment colection taking longer than incident delay timer | |
| 897 // environment colection taking longer than incident delay timer, and then | |
| 898 // another incident arriving | |
| OLD | NEW |