Home | History | Annotate | Download | only in safe_browsing
      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.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/file_util.h"
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/run_loop.h"
     12 #include "base/single_thread_task_runner.h"
     13 #include "chrome/browser/safe_browsing/two_phase_uploader.h"
     14 #include "chrome/common/chrome_switches.h"
     15 #include "chrome/common/safe_browsing/csd.pb.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "content/public/test/test_browser_thread_bundle.h"
     18 #include "net/url_request/url_request_test_util.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 namespace safe_browsing {
     22 
     23 namespace {
     24 
     25 class FakeUploader : public TwoPhaseUploader {
     26  public:
     27   FakeUploader(net::URLRequestContextGetter* url_request_context_getter,
     28                base::TaskRunner* file_task_runner,
     29                const GURL& base_url,
     30                const std::string& metadata,
     31                const base::FilePath& file_path,
     32                const ProgressCallback& progress_callback,
     33                const FinishCallback& finish_callback);
     34   virtual ~FakeUploader() {}
     35 
     36   virtual void Start() OVERRIDE {
     37     start_called_ = true;
     38   }
     39 
     40   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
     41   scoped_refptr<base::TaskRunner> file_task_runner_;
     42   GURL base_url_;
     43   std::string metadata_;
     44   base::FilePath file_path_;
     45   ProgressCallback progress_callback_;
     46   FinishCallback finish_callback_;
     47 
     48   bool start_called_;
     49 };
     50 
     51 FakeUploader::FakeUploader(
     52     net::URLRequestContextGetter* url_request_context_getter,
     53     base::TaskRunner* file_task_runner,
     54     const GURL& base_url,
     55     const std::string& metadata,
     56     const base::FilePath& file_path,
     57     const ProgressCallback& progress_callback,
     58     const FinishCallback& finish_callback)
     59     : url_request_context_getter_(url_request_context_getter),
     60       file_task_runner_(file_task_runner),
     61       base_url_(base_url),
     62       metadata_(metadata),
     63       file_path_(file_path),
     64       progress_callback_(progress_callback),
     65       finish_callback_(finish_callback),
     66       start_called_(false) {
     67 }
     68 
     69 class FakeUploaderFactory : public TwoPhaseUploaderFactory {
     70  public:
     71   FakeUploaderFactory() : uploader_(NULL) {}
     72   virtual ~FakeUploaderFactory() {}
     73 
     74   virtual TwoPhaseUploader* CreateTwoPhaseUploader(
     75       net::URLRequestContextGetter* url_request_context_getter,
     76       base::TaskRunner* file_task_runner,
     77       const GURL& base_url,
     78       const std::string& metadata,
     79       const base::FilePath& file_path,
     80       const TwoPhaseUploader::ProgressCallback& progress_callback,
     81       const TwoPhaseUploader::FinishCallback& finish_callback) OVERRIDE;
     82 
     83   FakeUploader* uploader_;
     84 };
     85 
     86 TwoPhaseUploader* FakeUploaderFactory::CreateTwoPhaseUploader(
     87     net::URLRequestContextGetter* url_request_context_getter,
     88     base::TaskRunner* file_task_runner,
     89     const GURL& base_url,
     90     const std::string& metadata,
     91     const base::FilePath& file_path,
     92     const TwoPhaseUploader::ProgressCallback& progress_callback,
     93     const TwoPhaseUploader::FinishCallback& finish_callback) {
     94   EXPECT_FALSE(uploader_);
     95 
     96   uploader_ = new FakeUploader(url_request_context_getter, file_task_runner,
     97                                base_url, metadata, file_path, progress_callback,
     98                                finish_callback);
     99   return uploader_;
    100 }
    101 
    102 }  // namespace
    103 
    104 class DownloadFeedbackTest : public testing::Test {
    105  public:
    106   DownloadFeedbackTest()
    107       : file_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread(
    108             content::BrowserThread::FILE)),
    109         io_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread(
    110             content::BrowserThread::IO)),
    111         url_request_context_getter_(
    112             new net::TestURLRequestContextGetter(io_task_runner_)),
    113         feedback_finish_called_(false) {
    114     EXPECT_NE(io_task_runner_, file_task_runner_);
    115   }
    116 
    117   virtual void SetUp() OVERRIDE {
    118     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    119     upload_file_path_ = temp_dir_.path().AppendASCII("test file");
    120     upload_file_data_ = "data";
    121     ASSERT_EQ(static_cast<int>(upload_file_data_.size()),
    122               file_util::WriteFile(upload_file_path_, upload_file_data_.data(),
    123                                    upload_file_data_.size()));
    124     TwoPhaseUploader::RegisterFactory(&two_phase_uploader_factory_);
    125   }
    126 
    127   virtual void TearDown() OVERRIDE {
    128     TwoPhaseUploader::RegisterFactory(NULL);
    129   }
    130 
    131   FakeUploader* uploader() const {
    132     return two_phase_uploader_factory_.uploader_;
    133   }
    134 
    135   void FinishCallback(DownloadFeedback* feedback) {
    136     EXPECT_FALSE(feedback_finish_called_);
    137     feedback_finish_called_ = true;
    138     delete feedback;
    139   }
    140 
    141  protected:
    142   base::ScopedTempDir temp_dir_;
    143   base::FilePath upload_file_path_;
    144   std::string upload_file_data_;
    145   content::TestBrowserThreadBundle thread_bundle_;
    146   scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
    147   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
    148   FakeUploaderFactory two_phase_uploader_factory_;
    149   scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
    150 
    151   bool feedback_finish_called_;
    152 };
    153 
    154 TEST_F(DownloadFeedbackTest, CompleteUpload) {
    155   ClientDownloadReport expected_report_metadata;
    156   expected_report_metadata.mutable_download_request()->set_url("http://test");
    157   expected_report_metadata.mutable_download_request()->set_length(
    158       upload_file_data_.size());
    159   expected_report_metadata.mutable_download_request()->mutable_digests(
    160       )->set_sha1("hi");
    161   expected_report_metadata.mutable_download_response()->set_verdict(
    162       ClientDownloadResponse::DANGEROUS_HOST);
    163   std::string ping_request(
    164       expected_report_metadata.download_request().SerializeAsString());
    165   std::string ping_response(
    166       expected_report_metadata.download_response().SerializeAsString());
    167 
    168   const char kTestFeedbackURL[] = "https://example.com/test/upload";
    169   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    170       switches::kSbDownloadFeedbackURL, kTestFeedbackURL);
    171 
    172   DownloadFeedback* feedback =
    173       DownloadFeedback::Create(url_request_context_getter_.get(),
    174                                file_task_runner_.get(),
    175                                upload_file_path_,
    176                                ping_request,
    177                                ping_response);
    178   EXPECT_FALSE(uploader());
    179 
    180   feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback,
    181                              base::Unretained(this),
    182                              feedback));
    183   ASSERT_TRUE(uploader());
    184   EXPECT_FALSE(feedback_finish_called_);
    185   EXPECT_TRUE(uploader()->start_called_);
    186 
    187   EXPECT_EQ(url_request_context_getter_,
    188             uploader()->url_request_context_getter_);
    189   EXPECT_EQ(file_task_runner_, uploader()->file_task_runner_);
    190   EXPECT_EQ(upload_file_path_, uploader()->file_path_);
    191   EXPECT_EQ(expected_report_metadata.SerializeAsString(),
    192             uploader()->metadata_);
    193   EXPECT_EQ(kTestFeedbackURL, uploader()->base_url_.spec());
    194 
    195   EXPECT_TRUE(base::PathExists(upload_file_path_));
    196 
    197   EXPECT_FALSE(feedback_finish_called_);
    198   uploader()->finish_callback_.Run(
    199       TwoPhaseUploader::STATE_SUCCESS, net::OK, 0, "");
    200   EXPECT_TRUE(feedback_finish_called_);
    201   base::RunLoop().RunUntilIdle();
    202   EXPECT_FALSE(base::PathExists(upload_file_path_));
    203 }
    204 
    205 TEST_F(DownloadFeedbackTest, CancelUpload) {
    206   ClientDownloadReport expected_report_metadata;
    207   expected_report_metadata.mutable_download_request()->set_url("http://test");
    208   expected_report_metadata.mutable_download_request()->set_length(
    209       upload_file_data_.size());
    210   expected_report_metadata.mutable_download_request()->mutable_digests(
    211       )->set_sha1("hi");
    212   expected_report_metadata.mutable_download_response()->set_verdict(
    213       ClientDownloadResponse::DANGEROUS_HOST);
    214   std::string ping_request(
    215       expected_report_metadata.download_request().SerializeAsString());
    216   std::string ping_response(
    217       expected_report_metadata.download_response().SerializeAsString());
    218 
    219   DownloadFeedback* feedback =
    220       DownloadFeedback::Create(url_request_context_getter_.get(),
    221                                file_task_runner_.get(),
    222                                upload_file_path_,
    223                                ping_request,
    224                                ping_response);
    225   EXPECT_FALSE(uploader());
    226 
    227   feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback,
    228                              base::Unretained(this),
    229                              feedback));
    230   ASSERT_TRUE(uploader());
    231   EXPECT_FALSE(feedback_finish_called_);
    232   EXPECT_TRUE(uploader()->start_called_);
    233   EXPECT_TRUE(base::PathExists(upload_file_path_));
    234 
    235   delete feedback;
    236   EXPECT_FALSE(feedback_finish_called_);
    237 
    238   base::RunLoop().RunUntilIdle();
    239   EXPECT_FALSE(base::PathExists(upload_file_path_));
    240 }
    241 
    242 }  // namespace safe_browsing
    243