| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/safe_browsing/download_feedback_service.h" | 5 #include "chrome/browser/safe_browsing/download_feedback_service.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/files/scoped_temp_dir.h" | 13 #include "base/files/scoped_temp_dir.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "chrome/browser/safe_browsing/download_feedback.h" | 17 #include "chrome/browser/safe_browsing/download_feedback.h" |
| 18 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
| 19 #include "content/public/test/mock_download_item.h" | 19 #include "content/public/test/mock_download_item.h" |
| 20 #include "content/public/test/test_browser_thread_bundle.h" | 20 #include "content/public/test/test_browser_thread_bundle.h" |
| 21 #include "net/url_request/url_request_test_util.h" | 21 #include "net/url_request/url_request_test_util.h" |
| 22 #include "testing/gmock/include/gmock/gmock.h" | 22 #include "testing/gmock/include/gmock/gmock.h" |
| 23 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 24 | 24 |
| 25 using ::testing::_; | 25 using ::testing::_; |
| 26 using ::testing::Return; | 26 using ::testing::Return; |
| 27 using ::testing::ReturnRef; |
| 27 using ::testing::SaveArg; | 28 using ::testing::SaveArg; |
| 28 | 29 |
| 29 namespace safe_browsing { | 30 namespace safe_browsing { |
| 30 | 31 |
| 31 namespace { | 32 namespace { |
| 32 | 33 |
| 33 class FakeDownloadFeedback : public DownloadFeedback { | 34 class FakeDownloadFeedback : public DownloadFeedback { |
| 34 public: | 35 public: |
| 35 FakeDownloadFeedback(net::URLRequestContextGetter* request_context_getter, | 36 FakeDownloadFeedback(net::URLRequestContextGetter* request_context_getter, |
| 36 base::TaskRunner* file_task_runner, | 37 base::TaskRunner* file_task_runner, |
| 37 const base::FilePath& file_path, | 38 const base::FilePath& file_path, |
| 38 const std::string& ping_request, | 39 const std::string& ping_request, |
| 39 const std::string& ping_response, | 40 const std::string& ping_response, |
| 40 base::Closure deletion_callback) | 41 base::Closure deletion_callback) |
| 41 : ping_request_(ping_request), | 42 : ping_request_(ping_request), |
| 42 ping_response_(ping_response), | 43 ping_response_(ping_response), |
| 43 deletion_callback_(deletion_callback), | 44 deletion_callback_(deletion_callback), |
| 44 start_called_(false) { | 45 start_called_(false) {} |
| 45 } | |
| 46 | 46 |
| 47 ~FakeDownloadFeedback() override { deletion_callback_.Run(); } | 47 ~FakeDownloadFeedback() override { deletion_callback_.Run(); } |
| 48 | 48 |
| 49 void Start(const base::Closure& finish_callback) override { | 49 void Start(const base::Closure& finish_callback) override { |
| 50 start_called_ = true; | 50 start_called_ = true; |
| 51 finish_callback_ = finish_callback; | 51 finish_callback_ = finish_callback; |
| 52 } | 52 } |
| 53 | 53 |
| 54 const std::string& GetPingRequestForTesting() const override { | 54 const std::string& GetPingRequestForTesting() const override { |
| 55 return ping_request_; | 55 return ping_request_; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 83 public: | 83 public: |
| 84 ~FakeDownloadFeedbackFactory() override {} | 84 ~FakeDownloadFeedbackFactory() override {} |
| 85 | 85 |
| 86 std::unique_ptr<DownloadFeedback> CreateDownloadFeedback( | 86 std::unique_ptr<DownloadFeedback> CreateDownloadFeedback( |
| 87 net::URLRequestContextGetter* request_context_getter, | 87 net::URLRequestContextGetter* request_context_getter, |
| 88 base::TaskRunner* file_task_runner, | 88 base::TaskRunner* file_task_runner, |
| 89 const base::FilePath& file_path, | 89 const base::FilePath& file_path, |
| 90 const std::string& ping_request, | 90 const std::string& ping_request, |
| 91 const std::string& ping_response) override { | 91 const std::string& ping_response) override { |
| 92 FakeDownloadFeedback* feedback = new FakeDownloadFeedback( | 92 FakeDownloadFeedback* feedback = new FakeDownloadFeedback( |
| 93 request_context_getter, | 93 request_context_getter, file_task_runner, file_path, ping_request, |
| 94 file_task_runner, | |
| 95 file_path, | |
| 96 ping_request, | |
| 97 ping_response, | 94 ping_response, |
| 98 base::Bind(&FakeDownloadFeedbackFactory::DownloadFeedbackDeleted, | 95 base::Bind(&FakeDownloadFeedbackFactory::DownloadFeedbackSent, |
| 99 base::Unretained(this), | 96 base::Unretained(this), feedbacks_.size())); |
| 100 feedbacks_.size())); | |
| 101 feedbacks_.push_back(feedback); | 97 feedbacks_.push_back(feedback); |
| 102 return base::WrapUnique(feedback); | 98 return base::WrapUnique(feedback); |
| 103 } | 99 } |
| 104 | 100 |
| 105 void DownloadFeedbackDeleted(size_t n) { feedbacks_[n] = nullptr; } | 101 void DownloadFeedbackSent(size_t n) { feedbacks_[n] = nullptr; } |
| 106 | 102 |
| 107 FakeDownloadFeedback* feedback(size_t n) const { | 103 FakeDownloadFeedback* feedback(size_t n) const { |
| 108 return feedbacks_[n]; | 104 return feedbacks_[n]; |
| 109 } | 105 } |
| 110 | 106 |
| 111 size_t num_feedbacks() const { | 107 size_t num_feedbacks() const { |
| 112 return feedbacks_.size(); | 108 return feedbacks_.size(); |
| 113 } | 109 } |
| 114 | 110 |
| 115 private: | 111 private: |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 | 182 |
| 187 EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, bad_size)); | 183 EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, bad_size)); |
| 188 EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, bad_size)); | 184 EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, bad_size)); |
| 189 EXPECT_FALSE(WillStorePings(DownloadProtectionService::UNCOMMON, bad_size)); | 185 EXPECT_FALSE(WillStorePings(DownloadProtectionService::UNCOMMON, bad_size)); |
| 190 EXPECT_FALSE( | 186 EXPECT_FALSE( |
| 191 WillStorePings(DownloadProtectionService::DANGEROUS_HOST, bad_size)); | 187 WillStorePings(DownloadProtectionService::DANGEROUS_HOST, bad_size)); |
| 192 EXPECT_FALSE(WillStorePings(DownloadProtectionService::POTENTIALLY_UNWANTED, | 188 EXPECT_FALSE(WillStorePings(DownloadProtectionService::POTENTIALLY_UNWANTED, |
| 193 bad_size)); | 189 bad_size)); |
| 194 } | 190 } |
| 195 | 191 |
| 196 TEST_F(DownloadFeedbackServiceTest, SingleFeedbackComplete) { | 192 TEST_F(DownloadFeedbackServiceTest, SingleFeedbackCompleteAndDiscardDownload) { |
| 197 const base::FilePath file_path(CreateTestFile(0)); | 193 const base::FilePath file_path(CreateTestFile(0)); |
| 198 const std::string ping_request = "ping"; | 194 const std::string ping_request = "ping"; |
| 199 const std::string ping_response = "resp"; | 195 const std::string ping_response = "resp"; |
| 200 | 196 |
| 201 content::DownloadItem::AcquireFileCallback download_discarded_callback; | 197 content::DownloadItem::AcquireFileCallback download_discarded_callback; |
| 202 | 198 |
| 203 content::MockDownloadItem item; | 199 content::MockDownloadItem item; |
| 204 EXPECT_CALL(item, GetDangerType()) | 200 EXPECT_CALL(item, GetDangerType()) |
| 205 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); | 201 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); |
| 206 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(1000)); | 202 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(1000)); |
| 207 EXPECT_CALL(item, StealDangerousDownload(_)) | 203 EXPECT_CALL(item, |
| 208 .WillOnce(SaveArg<0>(&download_discarded_callback)); | 204 StealDangerousDownload(true /*delete_file_after_feedback*/, _)) |
| 205 .WillOnce(SaveArg<1>(&download_discarded_callback)); |
| 209 | 206 |
| 210 DownloadFeedbackService service(request_context_getter_.get(), | 207 DownloadFeedbackService service(request_context_getter_.get(), |
| 211 file_task_runner_.get()); | 208 file_task_runner_.get()); |
| 212 service.MaybeStorePingsForDownload( | 209 service.MaybeStorePingsForDownload( |
| 213 DownloadProtectionService::UNCOMMON, &item, ping_request, ping_response); | 210 DownloadProtectionService::UNCOMMON, &item, ping_request, ping_response); |
| 214 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item)); | 211 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item)); |
| 215 service.BeginFeedbackForDownload(&item); | 212 service.BeginFeedbackForDownload(&item, DownloadCommands::DISCARD); |
| 216 ASSERT_FALSE(download_discarded_callback.is_null()); | 213 ASSERT_FALSE(download_discarded_callback.is_null()); |
| 217 EXPECT_EQ(0U, num_feedbacks()); | 214 EXPECT_EQ(0U, num_feedbacks()); |
| 218 | 215 |
| 216 download_discarded_callback.Run(file_path); |
| 217 ASSERT_EQ(1U, num_feedbacks()); |
| 218 ASSERT_TRUE(feedback(0)); |
| 219 EXPECT_TRUE(feedback(0)->start_called()); |
| 220 EXPECT_EQ(ping_request, feedback(0)->GetPingRequestForTesting()); |
| 221 EXPECT_EQ(ping_response, feedback(0)->GetPingResponseForTesting()); |
| 222 |
| 223 feedback(0)->finish_callback().Run(); |
| 224 EXPECT_FALSE(feedback(0)); |
| 225 |
| 226 base::RunLoop().RunUntilIdle(); |
| 227 EXPECT_TRUE(base::PathExists(file_path)); |
| 228 } |
| 229 |
| 230 TEST_F(DownloadFeedbackServiceTest, SingleFeedbackCompleteAndKeepDownload) { |
| 231 const base::FilePath file_path(CreateTestFile(0)); |
| 232 const std::string ping_request = "ping"; |
| 233 const std::string ping_response = "resp"; |
| 234 |
| 235 content::DownloadItem::AcquireFileCallback download_discarded_callback; |
| 236 |
| 237 content::MockDownloadItem item; |
| 238 EXPECT_CALL(item, GetDangerType()) |
| 239 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); |
| 240 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(1000)); |
| 241 EXPECT_CALL(item, |
| 242 StealDangerousDownload(false /*delete_file_after_feedback*/, _)) |
| 243 .WillOnce(SaveArg<1>(&download_discarded_callback)); |
| 244 EXPECT_CALL(item, ValidateDangerousDownload()).Times(1); |
| 245 GURL empty_url; |
| 246 EXPECT_CALL(item, GetURL()).WillOnce(ReturnRef(empty_url)); |
| 247 |
| 248 DownloadFeedbackService service(request_context_getter_.get(), |
| 249 file_task_runner_.get()); |
| 250 service.MaybeStorePingsForDownload(DownloadProtectionService::UNCOMMON, &item, |
| 251 ping_request, ping_response); |
| 252 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item)); |
| 253 service.BeginFeedbackForDownload(&item, DownloadCommands::KEEP); |
| 254 ASSERT_FALSE(download_discarded_callback.is_null()); |
| 255 EXPECT_EQ(0U, num_feedbacks()); |
| 256 |
| 219 download_discarded_callback.Run(file_path); | 257 download_discarded_callback.Run(file_path); |
| 220 ASSERT_EQ(1U, num_feedbacks()); | 258 ASSERT_EQ(1U, num_feedbacks()); |
| 221 ASSERT_TRUE(feedback(0)); | 259 ASSERT_TRUE(feedback(0)); |
| 222 EXPECT_TRUE(feedback(0)->start_called()); | 260 EXPECT_TRUE(feedback(0)->start_called()); |
| 223 EXPECT_EQ(ping_request, feedback(0)->GetPingRequestForTesting()); | 261 EXPECT_EQ(ping_request, feedback(0)->GetPingRequestForTesting()); |
| 224 EXPECT_EQ(ping_response, feedback(0)->GetPingResponseForTesting()); | 262 EXPECT_EQ(ping_response, feedback(0)->GetPingResponseForTesting()); |
| 225 | 263 |
| 226 feedback(0)->finish_callback().Run(); | 264 feedback(0)->finish_callback().Run(); |
| 227 EXPECT_FALSE(feedback(0)); | 265 EXPECT_FALSE(feedback(0)); |
| 228 | 266 |
| 229 // File should still exist since our FakeDownloadFeedback does not delete it. | |
| 230 base::RunLoop().RunUntilIdle(); | 267 base::RunLoop().RunUntilIdle(); |
| 231 EXPECT_TRUE(base::PathExists(file_path)); | 268 EXPECT_TRUE(base::PathExists(file_path)); |
| 232 } | 269 } |
| 233 | 270 |
| 234 TEST_F(DownloadFeedbackServiceTest, MultiplePendingFeedbackComplete) { | 271 TEST_F(DownloadFeedbackServiceTest, MultiplePendingFeedbackComplete) { |
| 235 const std::string ping_request = "ping"; | 272 const std::string ping_request = "ping"; |
| 236 const std::string ping_response = "resp"; | 273 const std::string ping_response = "resp"; |
| 237 const size_t kNumDownloads = 3; | 274 const size_t kNumDownloads = 3; |
| 238 | 275 |
| 239 content::DownloadItem::AcquireFileCallback | 276 content::DownloadItem::AcquireFileCallback |
| 240 download_discarded_callback[kNumDownloads]; | 277 download_discarded_callback[kNumDownloads]; |
| 241 | 278 |
| 242 base::FilePath file_path[kNumDownloads]; | 279 base::FilePath file_path[kNumDownloads]; |
| 243 content::MockDownloadItem item[kNumDownloads]; | 280 content::MockDownloadItem item[kNumDownloads]; |
| 244 for (size_t i = 0; i < kNumDownloads; ++i) { | 281 for (size_t i = 0; i < kNumDownloads; ++i) { |
| 245 file_path[i] = CreateTestFile(i); | 282 file_path[i] = CreateTestFile(i); |
| 246 EXPECT_CALL(item[i], GetDangerType()) | 283 EXPECT_CALL(item[i], GetDangerType()) |
| 247 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); | 284 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); |
| 248 EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000)); | 285 EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000)); |
| 249 EXPECT_CALL(item[i], StealDangerousDownload(_)) | 286 EXPECT_CALL(item[i], StealDangerousDownload(true, _)) |
| 250 .WillOnce(SaveArg<0>(&download_discarded_callback[i])); | 287 .WillOnce(SaveArg<1>(&download_discarded_callback[i])); |
| 251 DownloadFeedbackService::MaybeStorePingsForDownload( | 288 DownloadFeedbackService::MaybeStorePingsForDownload( |
| 252 DownloadProtectionService::UNCOMMON, &item[i], ping_request, | 289 DownloadProtectionService::UNCOMMON, &item[i], ping_request, |
| 253 ping_response); | 290 ping_response); |
| 254 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i])); | 291 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i])); |
| 255 } | 292 } |
| 256 | 293 |
| 257 { | 294 { |
| 258 DownloadFeedbackService service(request_context_getter_.get(), | 295 DownloadFeedbackService service(request_context_getter_.get(), |
| 259 file_task_runner_.get()); | 296 file_task_runner_.get()); |
| 260 for (size_t i = 0; i < kNumDownloads; ++i) { | 297 for (size_t i = 0; i < kNumDownloads; ++i) { |
| 261 SCOPED_TRACE(i); | 298 SCOPED_TRACE(i); |
| 262 service.BeginFeedbackForDownload(&item[i]); | 299 service.BeginFeedbackForDownload(&item[i], DownloadCommands::DISCARD); |
| 263 ASSERT_FALSE(download_discarded_callback[i].is_null()); | 300 ASSERT_FALSE(download_discarded_callback[i].is_null()); |
| 264 } | 301 } |
| 265 EXPECT_EQ(0U, num_feedbacks()); | 302 EXPECT_EQ(0U, num_feedbacks()); |
| 266 | 303 |
| 267 for (size_t i = 0; i < kNumDownloads; ++i) { | 304 for (size_t i = 0; i < kNumDownloads; ++i) { |
| 268 download_discarded_callback[i].Run(file_path[i]); | 305 download_discarded_callback[i].Run(file_path[i]); |
| 269 } | 306 } |
| 270 | 307 |
| 271 ASSERT_EQ(3U, num_feedbacks()); | 308 ASSERT_EQ(3U, num_feedbacks()); |
| 272 EXPECT_TRUE(feedback(0)->start_called()); | 309 EXPECT_TRUE(feedback(0)->start_called()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 content::DownloadItem::AcquireFileCallback | 345 content::DownloadItem::AcquireFileCallback |
| 309 download_discarded_callback[kNumDownloads]; | 346 download_discarded_callback[kNumDownloads]; |
| 310 | 347 |
| 311 base::FilePath file_path[kNumDownloads]; | 348 base::FilePath file_path[kNumDownloads]; |
| 312 content::MockDownloadItem item[kNumDownloads]; | 349 content::MockDownloadItem item[kNumDownloads]; |
| 313 for (size_t i = 0; i < kNumDownloads; ++i) { | 350 for (size_t i = 0; i < kNumDownloads; ++i) { |
| 314 file_path[i] = CreateTestFile(i); | 351 file_path[i] = CreateTestFile(i); |
| 315 EXPECT_CALL(item[i], GetDangerType()) | 352 EXPECT_CALL(item[i], GetDangerType()) |
| 316 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); | 353 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); |
| 317 EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000)); | 354 EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000)); |
| 318 EXPECT_CALL(item[i], StealDangerousDownload(_)) | 355 EXPECT_CALL(item[i], StealDangerousDownload(true, _)) |
| 319 .WillOnce(SaveArg<0>(&download_discarded_callback[i])); | 356 .WillOnce(SaveArg<1>(&download_discarded_callback[i])); |
| 320 DownloadFeedbackService::MaybeStorePingsForDownload( | 357 DownloadFeedbackService::MaybeStorePingsForDownload( |
| 321 DownloadProtectionService::UNCOMMON, &item[i], ping_request, | 358 DownloadProtectionService::UNCOMMON, &item[i], ping_request, |
| 322 ping_response); | 359 ping_response); |
| 323 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i])); | 360 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i])); |
| 324 } | 361 } |
| 325 | 362 |
| 326 { | 363 { |
| 327 DownloadFeedbackService service(request_context_getter_.get(), | 364 DownloadFeedbackService service(request_context_getter_.get(), |
| 328 file_task_runner_.get()); | 365 file_task_runner_.get()); |
| 329 for (size_t i = 0; i < kNumDownloads; ++i) { | 366 for (size_t i = 0; i < kNumDownloads; ++i) { |
| 330 SCOPED_TRACE(i); | 367 SCOPED_TRACE(i); |
| 331 service.BeginFeedbackForDownload(&item[i]); | 368 service.BeginFeedbackForDownload(&item[i], DownloadCommands::DISCARD); |
| 332 ASSERT_FALSE(download_discarded_callback[i].is_null()); | 369 ASSERT_FALSE(download_discarded_callback[i].is_null()); |
| 333 } | 370 } |
| 334 EXPECT_EQ(0U, num_feedbacks()); | 371 EXPECT_EQ(0U, num_feedbacks()); |
| 335 | 372 |
| 336 download_discarded_callback[0].Run(file_path[0]); | 373 download_discarded_callback[0].Run(file_path[0]); |
| 337 ASSERT_EQ(1U, num_feedbacks()); | 374 ASSERT_EQ(1U, num_feedbacks()); |
| 338 ASSERT_TRUE(feedback(0)); | 375 ASSERT_TRUE(feedback(0)); |
| 339 EXPECT_TRUE(feedback(0)->start_called()); | 376 EXPECT_TRUE(feedback(0)->start_called()); |
| 340 | 377 |
| 341 download_discarded_callback[1].Run(file_path[1]); | 378 download_discarded_callback[1].Run(file_path[1]); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 367 // was deleted. | 404 // was deleted. |
| 368 EXPECT_FALSE(base::PathExists(file_path[2])); | 405 EXPECT_FALSE(base::PathExists(file_path[2])); |
| 369 | 406 |
| 370 // These files should still exist since the FakeDownloadFeedback does not | 407 // These files should still exist since the FakeDownloadFeedback does not |
| 371 // delete them. | 408 // delete them. |
| 372 EXPECT_TRUE(base::PathExists(file_path[0])); | 409 EXPECT_TRUE(base::PathExists(file_path[0])); |
| 373 EXPECT_TRUE(base::PathExists(file_path[1])); | 410 EXPECT_TRUE(base::PathExists(file_path[1])); |
| 374 } | 411 } |
| 375 | 412 |
| 376 } // namespace safe_browsing | 413 } // namespace safe_browsing |
| OLD | NEW |