Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / download_feedback_service_unittest.cc
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/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "chrome/browser/safe_browsing/download_feedback.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/test/mock_download_item.h"
14 #include "content/public/test/test_browser_thread_bundle.h"
15 #include "net/url_request/url_request_test_util.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 using ::testing::_;
20 using ::testing::Return;
21 using ::testing::SaveArg;
22
23 namespace safe_browsing {
24
25 namespace {
26
27 class FakeDownloadFeedback : public DownloadFeedback {
28  public:
29   FakeDownloadFeedback(net::URLRequestContextGetter* request_context_getter,
30                        base::TaskRunner* file_task_runner,
31                        const base::FilePath& file_path,
32                        const std::string& ping_request,
33                        const std::string& ping_response,
34                        base::Closure deletion_callback)
35       : ping_request_(ping_request),
36         ping_response_(ping_response),
37         deletion_callback_(deletion_callback),
38         start_called_(false) {
39   }
40
41   virtual ~FakeDownloadFeedback() {
42     deletion_callback_.Run();
43   }
44
45   virtual void Start(const base::Closure& finish_callback) OVERRIDE {
46     start_called_ = true;
47     finish_callback_ = finish_callback;
48   }
49
50   virtual const std::string& GetPingRequestForTesting() const OVERRIDE {
51     return ping_request_;
52   }
53
54   virtual const std::string& GetPingResponseForTesting() const OVERRIDE {
55     return ping_response_;
56   }
57
58   base::Closure finish_callback() const {
59     return finish_callback_;
60   }
61
62   bool start_called() const {
63     return start_called_;
64   }
65
66  private:
67   scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
68   scoped_refptr<base::TaskRunner> file_task_runner_;
69   base::FilePath file_path_;
70   std::string ping_request_;
71   std::string ping_response_;
72
73   base::Closure finish_callback_;
74   base::Closure deletion_callback_;
75   bool start_called_;
76 };
77
78 class FakeDownloadFeedbackFactory : public DownloadFeedbackFactory {
79  public:
80   virtual ~FakeDownloadFeedbackFactory() {}
81
82   virtual DownloadFeedback* CreateDownloadFeedback(
83       net::URLRequestContextGetter* request_context_getter,
84       base::TaskRunner* file_task_runner,
85       const base::FilePath& file_path,
86       const std::string& ping_request,
87       const std::string& ping_response) OVERRIDE {
88     FakeDownloadFeedback* feedback = new FakeDownloadFeedback(
89         request_context_getter,
90         file_task_runner,
91         file_path,
92         ping_request,
93         ping_response,
94         base::Bind(&FakeDownloadFeedbackFactory::DownloadFeedbackDeleted,
95                    base::Unretained(this),
96                    feedbacks_.size()));
97     feedbacks_.push_back(feedback);
98     return feedback;
99   }
100
101   void DownloadFeedbackDeleted(size_t n) {
102     feedbacks_[n] = NULL;
103   }
104
105   FakeDownloadFeedback* feedback(size_t n) const {
106     return feedbacks_[n];
107   }
108
109   size_t num_feedbacks() const {
110     return feedbacks_.size();
111   }
112
113  private:
114   std::vector<FakeDownloadFeedback*> feedbacks_;
115 };
116
117 bool WillStorePings(DownloadProtectionService::DownloadCheckResult result,
118                      int64 size) {
119   content::MockDownloadItem item;
120   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(size));
121
122   EXPECT_FALSE(DownloadFeedbackService::IsEnabledForDownload(item));
123   DownloadFeedbackService::MaybeStorePingsForDownload(result, &item, "a", "b");
124   return DownloadFeedbackService::IsEnabledForDownload(item);
125 }
126
127 }  // namespace
128
129 class DownloadFeedbackServiceTest : public testing::Test {
130  public:
131   DownloadFeedbackServiceTest()
132       : file_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread(
133             content::BrowserThread::FILE)),
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     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
142     DownloadFeedback::RegisterFactory(&download_feedback_factory_);
143   }
144
145   virtual void TearDown() OVERRIDE {
146     DownloadFeedback::RegisterFactory(NULL);
147   }
148
149   base::FilePath CreateTestFile(int n) const {
150     base::FilePath upload_file_path(
151         temp_dir_.path().AppendASCII("test file " + base::IntToString(n)));
152     const std::string upload_file_data = "data";
153     int wrote = base::WriteFile(
154         upload_file_path, upload_file_data.data(), upload_file_data.size());
155     EXPECT_EQ(static_cast<int>(upload_file_data.size()), wrote);
156     return upload_file_path;
157   }
158
159   FakeDownloadFeedback* feedback(size_t n) const {
160     return download_feedback_factory_.feedback(n);
161   }
162
163   size_t num_feedbacks() const {
164     return download_feedback_factory_.num_feedbacks();
165   }
166  protected:
167   base::ScopedTempDir temp_dir_;
168   content::TestBrowserThreadBundle thread_bundle_;
169   scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
170   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
171   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
172   FakeDownloadFeedbackFactory download_feedback_factory_;
173
174 };
175
176 TEST_F(DownloadFeedbackServiceTest, MaybeStorePingsForDownload) {
177   const int64 ok_size = DownloadFeedback::kMaxUploadSize;
178   const int64 bad_size = DownloadFeedback::kMaxUploadSize + 1;
179
180   EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, ok_size));
181   EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, ok_size));
182   EXPECT_TRUE(WillStorePings(DownloadProtectionService::UNCOMMON, ok_size));
183   EXPECT_TRUE(
184       WillStorePings(DownloadProtectionService::DANGEROUS_HOST, ok_size));
185
186   EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, bad_size));
187   EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, bad_size));
188   EXPECT_FALSE(WillStorePings(DownloadProtectionService::UNCOMMON, bad_size));
189   EXPECT_FALSE(
190       WillStorePings(DownloadProtectionService::DANGEROUS_HOST, bad_size));
191 }
192
193 TEST_F(DownloadFeedbackServiceTest, SingleFeedbackComplete) {
194   const base::FilePath file_path(CreateTestFile(0));
195   const std::string ping_request = "ping";
196   const std::string ping_response = "resp";
197
198   content::DownloadItem::AcquireFileCallback download_discarded_callback;
199
200   content::MockDownloadItem item;
201   EXPECT_CALL(item, GetDangerType())
202       .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
203   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(1000));
204   EXPECT_CALL(item, StealDangerousDownload(_))
205       .WillOnce(SaveArg<0>(&download_discarded_callback));
206
207   DownloadFeedbackService service(request_context_getter_.get(),
208                                   file_task_runner_.get());
209   service.MaybeStorePingsForDownload(
210       DownloadProtectionService::UNCOMMON, &item, ping_request, ping_response);
211   ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item));
212   service.BeginFeedbackForDownload(&item);
213   ASSERT_FALSE(download_discarded_callback.is_null());
214   EXPECT_EQ(0U, num_feedbacks());
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   // File should still exist since our FakeDownloadFeedback does not delete it.
227   base::RunLoop().RunUntilIdle();
228   EXPECT_TRUE(base::PathExists(file_path));
229 }
230
231 TEST_F(DownloadFeedbackServiceTest, MultiplePendingFeedbackComplete) {
232   const std::string ping_request = "ping";
233   const std::string ping_response = "resp";
234   const size_t num_downloads = 3;
235
236   content::DownloadItem::AcquireFileCallback
237       download_discarded_callback[num_downloads];
238
239   base::FilePath file_path[num_downloads];
240   content::MockDownloadItem item[num_downloads];
241   for (size_t i = 0; i < num_downloads; ++i) {
242     file_path[i] = CreateTestFile(i);
243     EXPECT_CALL(item[i], GetDangerType())
244         .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
245     EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000));
246     EXPECT_CALL(item[i], StealDangerousDownload(_))
247         .WillOnce(SaveArg<0>(&download_discarded_callback[i]));
248     DownloadFeedbackService::MaybeStorePingsForDownload(
249         DownloadProtectionService::UNCOMMON, &item[i], ping_request,
250         ping_response);
251     ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i]));
252   }
253
254   {
255     DownloadFeedbackService service(request_context_getter_.get(),
256                                     file_task_runner_.get());
257     for (size_t i = 0; i < num_downloads; ++i) {
258       SCOPED_TRACE(i);
259       service.BeginFeedbackForDownload(&item[i]);
260       ASSERT_FALSE(download_discarded_callback[i].is_null());
261     }
262     EXPECT_EQ(0U, num_feedbacks());
263
264     for (size_t i = 0; i < num_downloads; ++i) {
265       download_discarded_callback[i].Run(file_path[i]);
266     }
267
268     ASSERT_EQ(3U, num_feedbacks());
269     EXPECT_TRUE(feedback(0)->start_called());
270     EXPECT_FALSE(feedback(1)->start_called());
271     EXPECT_FALSE(feedback(2)->start_called());
272
273     feedback(0)->finish_callback().Run();
274
275     EXPECT_FALSE(feedback(0));
276     EXPECT_TRUE(feedback(1)->start_called());
277     EXPECT_FALSE(feedback(2)->start_called());
278
279     feedback(1)->finish_callback().Run();
280
281     EXPECT_FALSE(feedback(0));
282     EXPECT_FALSE(feedback(1));
283     EXPECT_TRUE(feedback(2)->start_called());
284
285     feedback(2)->finish_callback().Run();
286
287     EXPECT_FALSE(feedback(0));
288     EXPECT_FALSE(feedback(1));
289     EXPECT_FALSE(feedback(2));
290   }
291
292   base::RunLoop().RunUntilIdle();
293   // These files should still exist since the FakeDownloadFeedback does not
294   // delete them.
295   EXPECT_TRUE(base::PathExists(file_path[0]));
296   EXPECT_TRUE(base::PathExists(file_path[1]));
297   EXPECT_TRUE(base::PathExists(file_path[2]));
298 }
299
300 TEST_F(DownloadFeedbackServiceTest, MultiFeedbackWithIncomplete) {
301   const std::string ping_request = "ping";
302   const std::string ping_response = "resp";
303   const size_t num_downloads = 3;
304
305   content::DownloadItem::AcquireFileCallback
306       download_discarded_callback[num_downloads];
307
308   base::FilePath file_path[num_downloads];
309   content::MockDownloadItem item[num_downloads];
310   for (size_t i = 0; i < num_downloads; ++i) {
311     file_path[i] = CreateTestFile(i);
312     EXPECT_CALL(item[i], GetDangerType())
313         .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
314     EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000));
315     EXPECT_CALL(item[i], StealDangerousDownload(_))
316         .WillOnce(SaveArg<0>(&download_discarded_callback[i]));
317     DownloadFeedbackService::MaybeStorePingsForDownload(
318         DownloadProtectionService::UNCOMMON, &item[i], ping_request,
319         ping_response);
320     ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i]));
321   }
322
323   {
324     DownloadFeedbackService service(request_context_getter_.get(),
325                                     file_task_runner_.get());
326     for (size_t i = 0; i < num_downloads; ++i) {
327       SCOPED_TRACE(i);
328       service.BeginFeedbackForDownload(&item[i]);
329       ASSERT_FALSE(download_discarded_callback[i].is_null());
330     }
331     EXPECT_EQ(0U, num_feedbacks());
332
333     download_discarded_callback[0].Run(file_path[0]);
334     ASSERT_EQ(1U, num_feedbacks());
335     ASSERT_TRUE(feedback(0));
336     EXPECT_TRUE(feedback(0)->start_called());
337
338     download_discarded_callback[1].Run(file_path[1]);
339     ASSERT_EQ(2U, num_feedbacks());
340     ASSERT_TRUE(feedback(1));
341     EXPECT_FALSE(feedback(1)->start_called());
342
343     feedback(0)->finish_callback().Run();
344     EXPECT_FALSE(feedback(0));
345     EXPECT_TRUE(feedback(1)->start_called());
346   }
347
348   EXPECT_EQ(2U, num_feedbacks());
349   for (size_t i = 0; i < num_feedbacks(); ++i) {
350     SCOPED_TRACE(i);
351     EXPECT_FALSE(feedback(i));
352   }
353
354   // Running a download acquired callback after the DownloadFeedbackService is
355   // destroyed should delete the file.
356   download_discarded_callback[2].Run(file_path[2]);
357   EXPECT_EQ(2U, num_feedbacks());
358
359   // File should still exist since the FileUtilProxy task hasn't run yet.
360   EXPECT_TRUE(base::PathExists(file_path[2]));
361
362   base::RunLoop().RunUntilIdle();
363   // File should be deleted since the AcquireFileCallback ran after the service
364   // was deleted.
365   EXPECT_FALSE(base::PathExists(file_path[2]));
366
367   // These files should still exist since the FakeDownloadFeedback does not
368   // delete them.
369   EXPECT_TRUE(base::PathExists(file_path[0]));
370   EXPECT_TRUE(base::PathExists(file_path[1]));
371 }
372
373 }  // namespace safe_browsing