OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/safe_browsing/download_feedback_service.h" |
| 6 |
| 7 #include "base/command_line.h" |
| 8 #include "base/message_loop.h" |
| 9 #include "chrome/browser/safe_browsing/download_feedback.h" |
| 10 #include "chrome/common/chrome_switches.h" |
| 11 #include "content/public/test/mock_download_item.h" |
| 12 #include "content/public/test/test_browser_thread.h" |
| 13 #include "net/url_request/url_request_test_util.h" |
| 14 #include "testing/gmock/include/gmock/gmock.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 |
| 17 using ::testing::_; |
| 18 using ::testing::Return; |
| 19 using ::testing::SaveArg; |
| 20 |
| 21 namespace safe_browsing { |
| 22 |
| 23 namespace { |
| 24 |
| 25 class FakeDownloadFeedback : public DownloadFeedback { |
| 26 public: |
| 27 FakeDownloadFeedback(net::URLRequestContextGetter* request_context_getter, |
| 28 base::TaskRunner* file_task_runner, |
| 29 const base::FilePath& file_path, |
| 30 const std::string& ping_request, |
| 31 const std::string& ping_response, |
| 32 base::Closure deletion_callback) |
| 33 : ping_request_(ping_request), |
| 34 ping_response_(ping_response), |
| 35 deletion_callback_(deletion_callback), |
| 36 start_called_(false) { |
| 37 } |
| 38 |
| 39 virtual ~FakeDownloadFeedback() { |
| 40 deletion_callback_.Run(); |
| 41 } |
| 42 |
| 43 virtual void Start(const base::Closure& finish_callback) OVERRIDE { |
| 44 start_called_ = true; |
| 45 finish_callback_ = finish_callback; |
| 46 } |
| 47 |
| 48 virtual const std::string& GetPingRequestForTesting() const OVERRIDE { |
| 49 return ping_request_; |
| 50 } |
| 51 |
| 52 virtual const std::string& GetPingResponseForTesting() const OVERRIDE { |
| 53 return ping_response_; |
| 54 } |
| 55 |
| 56 base::Closure finish_callback() const { |
| 57 return finish_callback_; |
| 58 } |
| 59 |
| 60 bool start_called() const { |
| 61 return start_called_; |
| 62 } |
| 63 |
| 64 private: |
| 65 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
| 66 scoped_refptr<base::TaskRunner> file_task_runner_; |
| 67 base::FilePath file_path_; |
| 68 std::string ping_request_; |
| 69 std::string ping_response_; |
| 70 |
| 71 base::Closure finish_callback_; |
| 72 base::Closure deletion_callback_; |
| 73 bool start_called_; |
| 74 }; |
| 75 |
| 76 class FakeDownloadFeedbackFactory : public DownloadFeedbackFactory { |
| 77 public: |
| 78 virtual ~FakeDownloadFeedbackFactory() {} |
| 79 |
| 80 virtual DownloadFeedback* CreateDownloadFeedback( |
| 81 net::URLRequestContextGetter* request_context_getter, |
| 82 base::TaskRunner* file_task_runner, |
| 83 const base::FilePath& file_path, |
| 84 const std::string& ping_request, |
| 85 const std::string& ping_response) OVERRIDE { |
| 86 FakeDownloadFeedback* feedback = new FakeDownloadFeedback( |
| 87 request_context_getter, |
| 88 file_task_runner, |
| 89 file_path, |
| 90 ping_request, |
| 91 ping_response, |
| 92 base::Bind(&FakeDownloadFeedbackFactory::DownloadFeedbackDeleted, |
| 93 base::Unretained(this), |
| 94 feedbacks_.size())); |
| 95 feedbacks_.push_back(feedback); |
| 96 return feedback; |
| 97 } |
| 98 |
| 99 void DownloadFeedbackDeleted(size_t n) { |
| 100 feedbacks_[n] = NULL; |
| 101 } |
| 102 |
| 103 FakeDownloadFeedback* feedback(size_t n) const { |
| 104 return feedbacks_[n]; |
| 105 } |
| 106 |
| 107 size_t num_feedbacks() const { |
| 108 return feedbacks_.size(); |
| 109 } |
| 110 |
| 111 private: |
| 112 std::vector<FakeDownloadFeedback*> feedbacks_; |
| 113 }; |
| 114 |
| 115 bool WillStorePings(DownloadProtectionService::DownloadCheckResult result, |
| 116 int64 size) { |
| 117 content::MockDownloadItem item; |
| 118 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(size)); |
| 119 |
| 120 EXPECT_FALSE(DownloadFeedbackService::IsEnabledForDownload(item)); |
| 121 DownloadFeedbackService::MaybeStorePingsForDownload(result, &item, "a", "b"); |
| 122 return DownloadFeedbackService::IsEnabledForDownload(item); |
| 123 } |
| 124 |
| 125 } // namespace |
| 126 |
| 127 class DownloadFeedbackServiceTest : public testing::Test { |
| 128 public: |
| 129 DownloadFeedbackServiceTest() |
| 130 : file_thread_(content::BrowserThread::FILE, &message_loop_), |
| 131 file_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread( |
| 132 content::BrowserThread::FILE)), |
| 133 io_thread_(content::BrowserThread::IO, &message_loop_), |
| 134 io_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread( |
| 135 content::BrowserThread::IO)), |
| 136 request_context_getter_( |
| 137 new net::TestURLRequestContextGetter(io_task_runner_)) { |
| 138 } |
| 139 |
| 140 virtual void SetUp() OVERRIDE { |
| 141 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 142 switches::kSbEnableDownloadFeedback); |
| 143 DownloadFeedback::RegisterFactory(&download_feedback_factory_); |
| 144 } |
| 145 |
| 146 virtual void TearDown() OVERRIDE { |
| 147 DownloadFeedback::RegisterFactory(NULL); |
| 148 } |
| 149 |
| 150 FakeDownloadFeedback* feedback(size_t n) const { |
| 151 return download_feedback_factory_.feedback(n); |
| 152 } |
| 153 |
| 154 size_t num_feedbacks() const { |
| 155 return download_feedback_factory_.num_feedbacks(); |
| 156 } |
| 157 protected: |
| 158 MessageLoop message_loop_; |
| 159 content::TestBrowserThread file_thread_; |
| 160 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; |
| 161 content::TestBrowserThread io_thread_; |
| 162 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
| 163 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; |
| 164 FakeDownloadFeedbackFactory download_feedback_factory_; |
| 165 |
| 166 }; |
| 167 |
| 168 TEST_F(DownloadFeedbackServiceTest, MaybeStorePingsForDownload) { |
| 169 const int64 ok_size = DownloadFeedback::kMaxUploadSize; |
| 170 const int64 bad_size = DownloadFeedback::kMaxUploadSize + 1; |
| 171 |
| 172 EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, ok_size)); |
| 173 EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, ok_size)); |
| 174 EXPECT_TRUE(WillStorePings(DownloadProtectionService::UNCOMMON, ok_size)); |
| 175 EXPECT_TRUE( |
| 176 WillStorePings(DownloadProtectionService::DANGEROUS_HOST, ok_size)); |
| 177 |
| 178 EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, bad_size)); |
| 179 EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, bad_size)); |
| 180 EXPECT_FALSE(WillStorePings(DownloadProtectionService::UNCOMMON, bad_size)); |
| 181 EXPECT_FALSE( |
| 182 WillStorePings(DownloadProtectionService::DANGEROUS_HOST, bad_size)); |
| 183 } |
| 184 |
| 185 TEST_F(DownloadFeedbackServiceTest, SingleFeedbackComplete) { |
| 186 const base::FilePath file_path(FILE_PATH_LITERAL("a.tmp")); |
| 187 const std::string ping_request = "ping"; |
| 188 const std::string ping_response = "resp"; |
| 189 |
| 190 content::DownloadItem::AcquireFileCallback download_discarded_callback; |
| 191 |
| 192 content::MockDownloadItem item; |
| 193 EXPECT_CALL(item, GetDangerType()) |
| 194 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); |
| 195 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(1000)); |
| 196 EXPECT_CALL(item, StealDangerousDownload(_)) |
| 197 .WillOnce(SaveArg<0>(&download_discarded_callback)); |
| 198 |
| 199 DownloadFeedbackService service(request_context_getter_, file_task_runner_); |
| 200 service.MaybeStorePingsForDownload( |
| 201 DownloadProtectionService::UNCOMMON, &item, ping_request, ping_response); |
| 202 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item)); |
| 203 service.BeginFeedbackForDownload(&item); |
| 204 ASSERT_FALSE(download_discarded_callback.is_null()); |
| 205 EXPECT_EQ(0U, num_feedbacks()); |
| 206 |
| 207 download_discarded_callback.Run(file_path); |
| 208 ASSERT_EQ(1U, num_feedbacks()); |
| 209 ASSERT_TRUE(feedback(0)); |
| 210 EXPECT_TRUE(feedback(0)->start_called()); |
| 211 EXPECT_EQ(ping_request, feedback(0)->GetPingRequestForTesting()); |
| 212 EXPECT_EQ(ping_response, feedback(0)->GetPingResponseForTesting()); |
| 213 |
| 214 feedback(0)->finish_callback().Run(); |
| 215 EXPECT_FALSE(feedback(0)); |
| 216 } |
| 217 |
| 218 TEST_F(DownloadFeedbackServiceTest, MultiFeedbackWithIncomplete) { |
| 219 const base::FilePath file_path(FILE_PATH_LITERAL("a.tmp")); |
| 220 const std::string ping_request = "ping"; |
| 221 const std::string ping_response = "resp"; |
| 222 const size_t num_downloads = 3; |
| 223 |
| 224 content::DownloadItem::AcquireFileCallback |
| 225 download_discarded_callback[num_downloads]; |
| 226 |
| 227 content::MockDownloadItem item[num_downloads]; |
| 228 for (size_t i = 0; i < num_downloads; ++i) { |
| 229 EXPECT_CALL(item[i], GetDangerType()) |
| 230 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); |
| 231 EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000)); |
| 232 EXPECT_CALL(item[i], StealDangerousDownload(_)) |
| 233 .WillOnce(SaveArg<0>(&download_discarded_callback[i])); |
| 234 DownloadFeedbackService::MaybeStorePingsForDownload( |
| 235 DownloadProtectionService::UNCOMMON, &item[i], ping_request, |
| 236 ping_response); |
| 237 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i])); |
| 238 } |
| 239 |
| 240 { |
| 241 DownloadFeedbackService service(request_context_getter_, file_task_runner_); |
| 242 for (size_t i = 0; i < num_downloads; ++i) { |
| 243 SCOPED_TRACE(i); |
| 244 service.BeginFeedbackForDownload(&item[i]); |
| 245 ASSERT_FALSE(download_discarded_callback[i].is_null()); |
| 246 } |
| 247 EXPECT_EQ(0U, num_feedbacks()); |
| 248 |
| 249 download_discarded_callback[0].Run(file_path); |
| 250 ASSERT_EQ(1U, num_feedbacks()); |
| 251 ASSERT_TRUE(feedback(0)); |
| 252 EXPECT_TRUE(feedback(0)->start_called()); |
| 253 |
| 254 download_discarded_callback[1].Run(file_path); |
| 255 ASSERT_EQ(2U, num_feedbacks()); |
| 256 ASSERT_TRUE(feedback(1)); |
| 257 EXPECT_TRUE(feedback(1)->start_called()); |
| 258 |
| 259 feedback(0)->finish_callback().Run(); |
| 260 EXPECT_FALSE(feedback(0)); |
| 261 } |
| 262 |
| 263 EXPECT_EQ(2U, num_feedbacks()); |
| 264 for (size_t i = 0; i < num_feedbacks(); ++i) { |
| 265 SCOPED_TRACE(i); |
| 266 EXPECT_FALSE(feedback(i)); |
| 267 } |
| 268 |
| 269 // Running a download acquired callback after the DownloadFeedbackService is |
| 270 // destroyed should do nothing. |
| 271 download_discarded_callback[2].Run(file_path); |
| 272 EXPECT_EQ(2U, num_feedbacks()); |
| 273 } |
| 274 |
| 275 } // namespace safe_browsing |
OLD | NEW |