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