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