Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / download_protection_service_unittest.cc
blob53d3bb2fe5e3601653cbbef97b72475d5e02516d
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/safe_browsing/download_protection_service.h"
7 #include <stdint.h>
8 #include <map>
9 #include <string>
11 #include "base/base_paths.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/message_loop/message_loop.h"
20 #include "base/path_service.h"
21 #include "base/run_loop.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/threading/sequenced_worker_pool.h"
24 #include "chrome/browser/history/history_service_factory.h"
25 #include "chrome/browser/safe_browsing/database_manager.h"
26 #include "chrome/browser/safe_browsing/download_feedback_service.h"
27 #include "chrome/browser/safe_browsing/local_database_manager.h"
28 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
29 #include "chrome/browser/safe_browsing/test_database_manager.h"
30 #include "chrome/common/safe_browsing/binary_feature_extractor.h"
31 #include "chrome/common/safe_browsing/csd.pb.h"
32 #include "chrome/test/base/testing_profile.h"
33 #include "components/history/core/browser/history_service.h"
34 #include "content/public/browser/download_danger_type.h"
35 #include "content/public/browser/page_navigator.h"
36 #include "content/public/test/mock_download_item.h"
37 #include "content/public/test/test_browser_thread_bundle.h"
38 #include "content/public/test/test_utils.h"
39 #include "net/base/url_util.h"
40 #include "net/cert/x509_certificate.h"
41 #include "net/http/http_status_code.h"
42 #include "net/url_request/test_url_fetcher_factory.h"
43 #include "net/url_request/url_fetcher_delegate.h"
44 #include "net/url_request/url_request_status.h"
45 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47 #include "third_party/zlib/google/zip.h"
48 #include "url/gurl.h"
50 using ::testing::Assign;
51 using ::testing::ContainerEq;
52 using ::testing::DoAll;
53 using ::testing::ElementsAre;
54 using ::testing::Invoke;
55 using ::testing::Mock;
56 using ::testing::NotNull;
57 using ::testing::Return;
58 using ::testing::ReturnRef;
59 using ::testing::SaveArg;
60 using ::testing::StrictMock;
61 using ::testing::_;
62 using base::MessageLoop;
63 using content::BrowserThread;
64 namespace safe_browsing {
65 namespace {
66 // A SafeBrowsingDatabaseManager implementation that returns a fixed result for
67 // a given URL.
68 class MockSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager {
69 public:
70 MockSafeBrowsingDatabaseManager() {}
72 MOCK_METHOD1(MatchDownloadWhitelistUrl, bool(const GURL&));
73 MOCK_METHOD1(MatchDownloadWhitelistString, bool(const std::string&));
74 MOCK_METHOD2(CheckDownloadUrl, bool(
75 const std::vector<GURL>& url_chain,
76 SafeBrowsingDatabaseManager::Client* client));
78 private:
79 virtual ~MockSafeBrowsingDatabaseManager() {}
80 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager);
83 class FakeSafeBrowsingService : public SafeBrowsingService {
84 public:
85 FakeSafeBrowsingService() { }
87 // Returned pointer has the same lifespan as the database_manager_ refcounted
88 // object.
89 MockSafeBrowsingDatabaseManager* mock_database_manager() {
90 return mock_database_manager_;
93 protected:
94 ~FakeSafeBrowsingService() override {}
96 SafeBrowsingDatabaseManager* CreateDatabaseManager() override {
97 mock_database_manager_ = new MockSafeBrowsingDatabaseManager();
98 return mock_database_manager_;
101 SafeBrowsingProtocolManagerDelegate* GetProtocolManagerDelegate() override {
102 // Our SafeBrowsingDatabaseManager doesn't implement this delegate.
103 return NULL;
106 void RegisterAllDelayedAnalysis() override {}
108 private:
109 MockSafeBrowsingDatabaseManager* mock_database_manager_;
111 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
114 class MockBinaryFeatureExtractor : public BinaryFeatureExtractor {
115 public:
116 MockBinaryFeatureExtractor() {}
117 MOCK_METHOD2(CheckSignature, void(const base::FilePath&,
118 ClientDownloadRequest_SignatureInfo*));
119 MOCK_METHOD4(ExtractImageFeatures, bool(
120 const base::FilePath&,
121 ExtractHeadersOption,
122 ClientDownloadRequest_ImageHeaders*,
123 google::protobuf::RepeatedPtrField<std::string>*));
125 protected:
126 virtual ~MockBinaryFeatureExtractor() {}
128 private:
129 DISALLOW_COPY_AND_ASSIGN(MockBinaryFeatureExtractor);
132 class TestURLFetcherWatcher : public net::TestURLFetcherDelegateForTests {
133 public:
134 explicit TestURLFetcherWatcher(net::TestURLFetcherFactory* factory)
135 : factory_(factory), fetcher_id_(-1) {
136 factory_->SetDelegateForTests(this);
138 ~TestURLFetcherWatcher() {
139 factory_->SetDelegateForTests(NULL);
142 // TestURLFetcherDelegateForTests impl:
143 void OnRequestStart(int fetcher_id) override {
144 fetcher_id_ = fetcher_id;
145 run_loop_.Quit();
147 void OnChunkUpload(int fetcher_id) override {}
148 void OnRequestEnd(int fetcher_id) override {}
150 int WaitForRequest() {
151 run_loop_.Run();
152 return fetcher_id_;
155 private:
156 net::TestURLFetcherFactory* factory_;
157 int fetcher_id_;
158 base::RunLoop run_loop_;
160 } // namespace
162 ACTION_P(SetCertificateContents, contents) {
163 arg1->add_certificate_chain()->add_element()->set_certificate(contents);
166 ACTION_P(SetDosHeaderContents, contents) {
167 arg2->mutable_pe_headers()->set_dos_header(contents);
168 return true;
171 ACTION_P(TrustSignature, certificate_file) {
172 arg1->set_trusted(true);
173 // Add a certificate chain. Note that we add the certificate twice so that
174 // it appears as its own issuer.
175 std::string cert_data;
176 ASSERT_TRUE(base::ReadFileToString(certificate_file, &cert_data));
177 ClientDownloadRequest_CertificateChain* chain =
178 arg1->add_certificate_chain();
179 chain->add_element()->set_certificate(cert_data);
180 chain->add_element()->set_certificate(cert_data);
183 // We can't call OnSafeBrowsingResult directly because SafeBrowsingCheck does
184 // not have any copy constructor which means it can't be stored in a callback
185 // easily. Note: check will be deleted automatically when the callback is
186 // deleted.
187 void OnSafeBrowsingResult(
188 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck* check) {
189 check->OnSafeBrowsingResult();
192 ACTION_P(CheckDownloadUrlDone, threat_type) {
193 // TODO(nparker): Remove use of SafeBrowsingCheck and instead call
194 // client->OnCheckDownloadUrlResult(..) directly.
195 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck* check =
196 new LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck(
197 arg0,
198 std::vector<SBFullHash>(),
199 arg1,
200 safe_browsing_util::BINURL,
201 std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL));
202 for (size_t i = 0; i < check->url_results.size(); ++i)
203 check->url_results[i] = threat_type;
204 BrowserThread::PostTask(BrowserThread::IO,
205 FROM_HERE,
206 base::Bind(&OnSafeBrowsingResult,
207 base::Owned(check)));
210 class DownloadProtectionServiceTest : public testing::Test {
211 protected:
212 DownloadProtectionServiceTest()
213 : test_browser_thread_bundle_(
214 content::TestBrowserThreadBundle::IO_MAINLOOP) {
216 void SetUp() override {
217 // Start real threads for the IO and File threads so that the DCHECKs
218 // to test that we're on the correct thread work.
219 sb_service_ = new StrictMock<FakeSafeBrowsingService>();
220 sb_service_->Initialize();
221 binary_feature_extractor_ = new StrictMock<MockBinaryFeatureExtractor>();
222 ON_CALL(*binary_feature_extractor_, ExtractImageFeatures(_, _, _, _))
223 .WillByDefault(Return(true));
224 download_service_ = sb_service_->download_protection_service();
225 download_service_->binary_feature_extractor_ = binary_feature_extractor_;
226 download_service_->SetEnabled(true);
227 client_download_request_subscription_ =
228 download_service_->RegisterClientDownloadRequestCallback(
229 base::Bind(&DownloadProtectionServiceTest::OnClientDownloadRequest,
230 base::Unretained(this)));
231 base::RunLoop().RunUntilIdle();
232 has_result_ = false;
234 base::FilePath source_path;
235 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &source_path));
236 testdata_path_ = source_path
237 .AppendASCII("chrome")
238 .AppendASCII("test")
239 .AppendASCII("data")
240 .AppendASCII("safe_browsing")
241 .AppendASCII("download_protection");
244 void TearDown() override {
245 client_download_request_subscription_.reset();
246 sb_service_->ShutDown();
247 // Flush all of the thread message loops to ensure that there are no
248 // tasks currently running.
249 FlushThreadMessageLoops();
250 sb_service_ = NULL;
253 bool RequestContainsResource(const ClientDownloadRequest& request,
254 ClientDownloadRequest::ResourceType type,
255 const std::string& url,
256 const std::string& referrer) {
257 for (int i = 0; i < request.resources_size(); ++i) {
258 if (request.resources(i).url() == url &&
259 request.resources(i).type() == type &&
260 (referrer.empty() || request.resources(i).referrer() == referrer)) {
261 return true;
264 return false;
267 // At this point we only set the server IP for the download itself.
268 bool RequestContainsServerIp(const ClientDownloadRequest& request,
269 const std::string& remote_address) {
270 for (int i = 0; i < request.resources_size(); ++i) {
271 // We want the last DOWNLOAD_URL in the chain.
272 if (request.resources(i).type() == ClientDownloadRequest::DOWNLOAD_URL &&
273 (i + 1 == request.resources_size() ||
274 request.resources(i + 1).type() !=
275 ClientDownloadRequest::DOWNLOAD_URL)) {
276 return remote_address == request.resources(i).remote_ip();
279 return false;
282 static const ClientDownloadRequest_ArchivedBinary* GetRequestArchivedBinary(
283 const ClientDownloadRequest& request,
284 const std::string& file_basename) {
285 for (const auto& archived_binary : request.archived_binary()) {
286 if (archived_binary.file_basename() == file_basename)
287 return &archived_binary;
289 return nullptr;
292 // Flushes any pending tasks in the message loops of all threads.
293 void FlushThreadMessageLoops() {
294 BrowserThread::GetBlockingPool()->FlushForTesting();
295 FlushMessageLoop(BrowserThread::IO);
296 base::RunLoop().RunUntilIdle();
299 // Proxy for private method.
300 static void GetCertificateWhitelistStrings(
301 const net::X509Certificate& certificate,
302 const net::X509Certificate& issuer,
303 std::vector<std::string>* whitelist_strings) {
304 DownloadProtectionService::GetCertificateWhitelistStrings(
305 certificate, issuer, whitelist_strings);
308 // Reads a single PEM-encoded certificate from the testdata directory.
309 // Returns NULL on failure.
310 scoped_refptr<net::X509Certificate> ReadTestCertificate(
311 const std::string& filename) {
312 std::string cert_data;
313 if (!base::ReadFileToString(testdata_path_.AppendASCII(filename),
314 &cert_data)) {
315 return NULL;
317 net::CertificateList certs =
318 net::X509Certificate::CreateCertificateListFromBytes(
319 cert_data.data(),
320 cert_data.size(),
321 net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
322 return certs.empty() ? NULL : certs[0];
325 const ClientDownloadRequest* GetClientDownloadRequest() const {
326 return last_client_download_request_.get();
329 bool HasClientDownloadRequest() const {
330 return last_client_download_request_.get() != NULL;
333 void ClearClientDownloadRequest() { last_client_download_request_.reset(); }
335 private:
336 // Helper functions for FlushThreadMessageLoops.
337 void RunAllPendingAndQuitUI() {
338 base::MessageLoop::current()->RunUntilIdle();
339 BrowserThread::PostTask(
340 BrowserThread::UI,
341 FROM_HERE,
342 base::Bind(&DownloadProtectionServiceTest::QuitMessageLoop,
343 base::Unretained(this)));
346 void QuitMessageLoop() {
347 base::MessageLoop::current()->Quit();
350 void PostRunMessageLoopTask(BrowserThread::ID thread) {
351 BrowserThread::PostTask(
352 thread,
353 FROM_HERE,
354 base::Bind(&DownloadProtectionServiceTest::RunAllPendingAndQuitUI,
355 base::Unretained(this)));
358 void FlushMessageLoop(BrowserThread::ID thread) {
359 BrowserThread::PostTask(
360 BrowserThread::UI,
361 FROM_HERE,
362 base::Bind(&DownloadProtectionServiceTest::PostRunMessageLoopTask,
363 base::Unretained(this), thread));
364 MessageLoop::current()->Run();
367 void OnClientDownloadRequest(content::DownloadItem* download,
368 const ClientDownloadRequest* request) {
369 if (request)
370 last_client_download_request_.reset(new ClientDownloadRequest(*request));
371 else
372 last_client_download_request_.reset();
375 public:
376 void CheckDoneCallback(
377 DownloadProtectionService::DownloadCheckResult result) {
378 result_ = result;
379 has_result_ = true;
380 MessageLoop::current()->Quit();
383 void SyncCheckDoneCallback(
384 DownloadProtectionService::DownloadCheckResult result) {
385 result_ = result;
386 has_result_ = true;
389 void SendURLFetchComplete(net::TestURLFetcher* fetcher) {
390 fetcher->delegate()->OnURLFetchComplete(fetcher);
393 testing::AssertionResult IsResult(
394 DownloadProtectionService::DownloadCheckResult expected) {
395 if (!has_result_)
396 return testing::AssertionFailure() << "No result";
397 has_result_ = false;
398 return result_ == expected ?
399 testing::AssertionSuccess() :
400 testing::AssertionFailure() << "Expected " << expected <<
401 ", got " << result_;
404 protected:
405 scoped_refptr<FakeSafeBrowsingService> sb_service_;
406 scoped_refptr<MockBinaryFeatureExtractor> binary_feature_extractor_;
407 DownloadProtectionService* download_service_;
408 DownloadProtectionService::DownloadCheckResult result_;
409 bool has_result_;
410 content::TestBrowserThreadBundle test_browser_thread_bundle_;
411 content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
412 base::FilePath testdata_path_;
413 DownloadProtectionService::ClientDownloadRequestSubscription
414 client_download_request_subscription_;
415 scoped_ptr<ClientDownloadRequest> last_client_download_request_;
418 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadInvalidUrl) {
419 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
420 base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
421 std::vector<GURL> url_chain;
422 GURL referrer("http://www.google.com/");
424 content::MockDownloadItem item;
425 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
426 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
427 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
428 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
429 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
430 EXPECT_CALL(item, GetTabReferrerUrl())
431 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
432 download_service_->CheckClientDownload(
433 &item,
434 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
435 base::Unretained(this)));
436 MessageLoop::current()->Run();
437 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
438 EXPECT_FALSE(HasClientDownloadRequest());
439 Mock::VerifyAndClearExpectations(&item);
441 url_chain.push_back(GURL("file://www.google.com/"));
442 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
443 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
444 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
445 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
446 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
447 EXPECT_CALL(item, GetTabReferrerUrl())
448 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
449 download_service_->CheckClientDownload(
450 &item,
451 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
452 base::Unretained(this)));
453 MessageLoop::current()->Run();
454 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
455 EXPECT_FALSE(HasClientDownloadRequest());
458 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadNotABinary) {
459 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
460 base::FilePath a_txt(FILE_PATH_LITERAL("a.txt"));
461 std::vector<GURL> url_chain;
462 GURL referrer("http://www.google.com/");
464 content::MockDownloadItem item;
465 url_chain.push_back(GURL("http://www.example.com/foo"));
466 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
467 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_txt));
468 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
469 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
470 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
471 EXPECT_CALL(item, GetTabReferrerUrl())
472 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
473 download_service_->CheckClientDownload(
474 &item,
475 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
476 base::Unretained(this)));
477 MessageLoop::current()->Run();
478 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
479 EXPECT_FALSE(HasClientDownloadRequest());
482 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadWhitelistedUrl) {
483 // Response to any requests will be DANGEROUS.
484 ClientDownloadResponse response;
485 response.set_verdict(ClientDownloadResponse::DANGEROUS);
486 net::FakeURLFetcherFactory factory(NULL);
487 factory.SetFakeResponse(
488 DownloadProtectionService::GetDownloadRequestUrl(),
489 response.SerializeAsString(),
490 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
492 std::string hash = "hash";
493 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
494 base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
495 std::vector<GURL> url_chain;
496 GURL referrer;
498 content::MockDownloadItem item;
499 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
500 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
501 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
502 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
503 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
504 EXPECT_CALL(item, GetTabReferrerUrl())
505 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
506 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
507 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
508 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
509 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
510 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
511 .Times(4);
512 EXPECT_CALL(*binary_feature_extractor_.get(),
513 ExtractImageFeatures(
514 a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _))
515 .Times(4);
517 // We should not get whilelist checks for other URLs than specified below.
518 EXPECT_CALL(*sb_service_->mock_database_manager(),
519 MatchDownloadWhitelistUrl(_)).Times(0);
520 EXPECT_CALL(*sb_service_->mock_database_manager(),
521 MatchDownloadWhitelistUrl(GURL("http://www.evil.com/bla.exe")))
522 .WillRepeatedly(Return(false));
523 EXPECT_CALL(*sb_service_->mock_database_manager(),
524 MatchDownloadWhitelistUrl(GURL("http://www.google.com/a.exe")))
525 .WillRepeatedly(Return(true));
527 // With no referrer and just the bad url, should be marked DANGEROUS.
528 url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
529 download_service_->CheckClientDownload(
530 &item,
531 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
532 base::Unretained(this)));
533 MessageLoop::current()->Run();
535 #if defined(OS_WIN) || defined(OS_MACOSX)
536 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
537 EXPECT_TRUE(HasClientDownloadRequest());
538 ClearClientDownloadRequest();
539 #else
540 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
541 EXPECT_FALSE(HasClientDownloadRequest());
542 #endif
544 // Check that the referrer is not matched against the whitelist.
545 referrer = GURL("http://www.google.com/");
546 download_service_->CheckClientDownload(
547 &item,
548 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
549 base::Unretained(this)));
550 MessageLoop::current()->Run();
552 #if defined(OS_WIN) || defined(OS_MACOSX)
553 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
554 EXPECT_TRUE(HasClientDownloadRequest());
555 ClearClientDownloadRequest();
556 #else
557 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
558 EXPECT_FALSE(HasClientDownloadRequest());
559 #endif
561 // Redirect from a site shouldn't be checked either.
562 url_chain.insert(url_chain.begin(), GURL("http://www.google.com/redirect"));
563 download_service_->CheckClientDownload(
564 &item,
565 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
566 base::Unretained(this)));
567 MessageLoop::current()->Run();
569 #if defined(OS_WIN) || defined(OS_MACOSX)
570 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
571 EXPECT_TRUE(HasClientDownloadRequest());
572 ClearClientDownloadRequest();
573 #else
574 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
575 EXPECT_FALSE(HasClientDownloadRequest());
576 #endif
578 // Only if the final url is whitelisted should it be SAFE.
579 url_chain.push_back(GURL("http://www.google.com/a.exe"));
580 download_service_->CheckClientDownload(
581 &item,
582 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
583 base::Unretained(this)));
584 MessageLoop::current()->Run();
585 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
586 // TODO(grt): Make the service produce the request even when the URL is
587 // whitelisted.
588 EXPECT_FALSE(HasClientDownloadRequest());
591 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadFetchFailed) {
592 net::FakeURLFetcherFactory factory(NULL);
593 // HTTP request will fail.
594 factory.SetFakeResponse(
595 DownloadProtectionService::GetDownloadRequestUrl(), std::string(),
596 net::HTTP_INTERNAL_SERVER_ERROR, net::URLRequestStatus::FAILED);
598 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
599 base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
600 std::vector<GURL> url_chain;
601 url_chain.push_back(GURL("http://www.evil.com/a.exe"));
602 GURL referrer("http://www.google.com/");
603 std::string hash = "hash";
605 content::MockDownloadItem item;
606 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
607 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
608 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
609 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
610 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
611 EXPECT_CALL(item, GetTabReferrerUrl())
612 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
613 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
614 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
615 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
616 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
618 EXPECT_CALL(*sb_service_->mock_database_manager(),
619 MatchDownloadWhitelistUrl(_))
620 .WillRepeatedly(Return(false));
621 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _));
622 EXPECT_CALL(
623 *binary_feature_extractor_.get(),
624 ExtractImageFeatures(a_tmp, BinaryFeatureExtractor::kDefaultOptions,
625 _, _));
627 download_service_->CheckClientDownload(
628 &item,
629 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
630 base::Unretained(this)));
631 MessageLoop::current()->Run();
632 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
635 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadSuccess) {
636 ClientDownloadResponse response;
637 response.set_verdict(ClientDownloadResponse::SAFE);
638 net::FakeURLFetcherFactory factory(NULL);
639 // Empty response means SAFE.
640 factory.SetFakeResponse(
641 DownloadProtectionService::GetDownloadRequestUrl(),
642 response.SerializeAsString(),
643 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
645 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
646 base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
647 std::vector<GURL> url_chain;
648 url_chain.push_back(GURL("http://www.evil.com/a.exe"));
649 GURL referrer("http://www.google.com/");
650 std::string hash = "hash";
652 content::MockDownloadItem item;
653 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
654 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
655 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
656 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
657 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
658 EXPECT_CALL(item, GetTabReferrerUrl())
659 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
660 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
661 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
662 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
663 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
665 EXPECT_CALL(*sb_service_->mock_database_manager(),
666 MatchDownloadWhitelistUrl(_))
667 .WillRepeatedly(Return(false));
668 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
669 .Times(6);
670 EXPECT_CALL(*binary_feature_extractor_.get(),
671 ExtractImageFeatures(
672 a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _))
673 .Times(6);
675 download_service_->CheckClientDownload(
676 &item,
677 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
678 base::Unretained(this)));
679 MessageLoop::current()->Run();
681 #if defined(OS_WIN) || defined(OS_MACOSX)
682 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
683 EXPECT_TRUE(HasClientDownloadRequest());
684 ClearClientDownloadRequest();
685 #else
686 // On !(OS_WIN || OS_MACOSX), no file types are currently supported. Hence all
687 // requests to CheckClientDownload() result in a verdict of UNKNOWN.
688 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
689 EXPECT_FALSE(HasClientDownloadRequest());
690 #endif
692 // Invalid response should result in UNKNOWN.
693 response.Clear();
694 factory.SetFakeResponse(
695 DownloadProtectionService::GetDownloadRequestUrl(),
696 response.SerializePartialAsString(),
697 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
699 download_service_->CheckClientDownload(
700 &item,
701 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
702 base::Unretained(this)));
703 MessageLoop::current()->Run();
704 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
705 #if defined(OS_WIN) || defined(OS_MACOSX)
706 EXPECT_TRUE(HasClientDownloadRequest());
707 ClearClientDownloadRequest();
708 #else
709 EXPECT_FALSE(HasClientDownloadRequest());
710 #endif
711 std::string feedback_ping;
712 std::string feedback_response;
713 EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
714 item, &feedback_ping, &feedback_response));
716 // If the response is dangerous the result should also be marked as dangerous.
717 response.set_verdict(ClientDownloadResponse::DANGEROUS);
718 factory.SetFakeResponse(
719 DownloadProtectionService::GetDownloadRequestUrl(),
720 response.SerializeAsString(),
721 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
723 download_service_->CheckClientDownload(
724 &item,
725 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
726 base::Unretained(this)));
727 MessageLoop::current()->Run();
728 EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
729 item, &feedback_ping, &feedback_response));
731 #if defined(OS_WIN) || defined(OS_MACOSX)
732 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
733 EXPECT_TRUE(HasClientDownloadRequest());
734 ClearClientDownloadRequest();
735 #else
736 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
737 EXPECT_FALSE(HasClientDownloadRequest());
738 #endif
740 // If the response is uncommon the result should also be marked as uncommon.
741 response.set_verdict(ClientDownloadResponse::UNCOMMON);
742 factory.SetFakeResponse(
743 DownloadProtectionService::GetDownloadRequestUrl(),
744 response.SerializeAsString(),
745 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
747 download_service_->CheckClientDownload(
748 &item,
749 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
750 base::Unretained(this)));
751 MessageLoop::current()->Run();
752 #if defined(OS_WIN) || defined(OS_MACOSX)
753 EXPECT_TRUE(IsResult(DownloadProtectionService::UNCOMMON));
754 EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting(
755 item, &feedback_ping, &feedback_response));
756 ClientDownloadRequest decoded_request;
757 EXPECT_TRUE(decoded_request.ParseFromString(feedback_ping));
758 EXPECT_EQ(url_chain.back().spec(), decoded_request.url());
759 EXPECT_EQ(response.SerializeAsString(), feedback_response);
760 EXPECT_TRUE(HasClientDownloadRequest());
761 ClearClientDownloadRequest();
762 #else
763 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
764 #endif
766 // If the response is dangerous_host the result should also be marked as
767 // dangerous_host.
768 response.set_verdict(ClientDownloadResponse::DANGEROUS_HOST);
769 factory.SetFakeResponse(
770 DownloadProtectionService::GetDownloadRequestUrl(),
771 response.SerializeAsString(),
772 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
774 download_service_->CheckClientDownload(
775 &item,
776 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
777 base::Unretained(this)));
778 MessageLoop::current()->Run();
779 #if defined(OS_WIN) || defined(OS_MACOSX)
780 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS_HOST));
781 EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting(
782 item, &feedback_ping, &feedback_response));
783 EXPECT_EQ(response.SerializeAsString(), feedback_response);
784 EXPECT_TRUE(HasClientDownloadRequest());
785 ClearClientDownloadRequest();
786 #else
787 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
788 #endif
790 // If the response is POTENTIALLY_UNWANTED the result should also be marked as
791 // POTENTIALLY_UNWANTED.
792 response.set_verdict(ClientDownloadResponse::POTENTIALLY_UNWANTED);
793 factory.SetFakeResponse(
794 DownloadProtectionService::GetDownloadRequestUrl(),
795 response.SerializeAsString(),
796 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
798 download_service_->CheckClientDownload(
799 &item,
800 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
801 base::Unretained(this)));
802 MessageLoop::current()->Run();
804 #if defined(OS_WIN) || defined(OS_MACOSX)
805 EXPECT_TRUE(IsResult(DownloadProtectionService::POTENTIALLY_UNWANTED));
806 EXPECT_TRUE(HasClientDownloadRequest());
807 ClearClientDownloadRequest();
808 #else
809 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
810 EXPECT_FALSE(HasClientDownloadRequest());
811 #endif
814 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadHTTPS) {
815 ClientDownloadResponse response;
816 response.set_verdict(ClientDownloadResponse::DANGEROUS);
817 net::FakeURLFetcherFactory factory(NULL);
818 factory.SetFakeResponse(
819 DownloadProtectionService::GetDownloadRequestUrl(),
820 response.SerializeAsString(),
821 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
823 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
824 base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
825 std::vector<GURL> url_chain;
826 url_chain.push_back(GURL("http://www.evil.com/a.exe"));
827 GURL referrer("http://www.google.com/");
828 std::string hash = "hash";
830 content::MockDownloadItem item;
831 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
832 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
833 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
834 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
835 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
836 EXPECT_CALL(item, GetTabReferrerUrl())
837 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
838 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
839 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
840 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
841 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
843 EXPECT_CALL(*sb_service_->mock_database_manager(),
844 MatchDownloadWhitelistUrl(_))
845 .WillRepeatedly(Return(false));
846 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
847 .Times(1);
848 EXPECT_CALL(*binary_feature_extractor_.get(),
849 ExtractImageFeatures(
850 a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _))
851 .Times(1);
853 download_service_->CheckClientDownload(
854 &item,
855 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
856 base::Unretained(this)));
857 MessageLoop::current()->Run();
859 #if defined(OS_WIN) || defined(OS_MACOSX)
860 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
861 EXPECT_TRUE(HasClientDownloadRequest());
862 ClearClientDownloadRequest();
863 #else
864 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
865 EXPECT_FALSE(HasClientDownloadRequest());
866 #endif
869 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadBlob) {
870 ClientDownloadResponse response;
871 response.set_verdict(ClientDownloadResponse::DANGEROUS);
872 net::FakeURLFetcherFactory factory(NULL);
873 factory.SetFakeResponse(DownloadProtectionService::GetDownloadRequestUrl(),
874 response.SerializeAsString(), net::HTTP_OK,
875 net::URLRequestStatus::SUCCESS);
877 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
878 base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
879 std::vector<GURL> url_chain;
880 url_chain.push_back(
881 GURL("blob:http://www.evil.com/50b85f60-71e4-11e4-82f8-0800200c9a66"));
882 GURL referrer("http://www.google.com/");
883 std::string hash = "hash";
885 content::MockDownloadItem item;
886 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
887 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
888 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
889 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
890 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
891 EXPECT_CALL(item, GetTabReferrerUrl())
892 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
893 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
894 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
895 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
896 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
898 EXPECT_CALL(*sb_service_->mock_database_manager(),
899 MatchDownloadWhitelistUrl(_)).WillRepeatedly(Return(false));
900 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
901 .Times(1);
902 EXPECT_CALL(*binary_feature_extractor_.get(),
903 ExtractImageFeatures(
904 a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _))
905 .Times(1);
907 download_service_->CheckClientDownload(
908 &item,
909 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
910 base::Unretained(this)));
911 MessageLoop::current()->Run();
913 #if defined(OS_WIN) || defined(OS_MACOSX)
914 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
915 EXPECT_TRUE(HasClientDownloadRequest());
916 ClearClientDownloadRequest();
917 #else
918 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
919 EXPECT_FALSE(HasClientDownloadRequest());
920 #endif
923 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadData) {
924 ClientDownloadResponse response;
925 response.set_verdict(ClientDownloadResponse::DANGEROUS);
926 net::FakeURLFetcherFactory factory(NULL);
927 factory.SetFakeResponse(DownloadProtectionService::GetDownloadRequestUrl(),
928 response.SerializeAsString(), net::HTTP_OK,
929 net::URLRequestStatus::SUCCESS);
931 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
932 base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
933 std::vector<GURL> url_chain;
934 url_chain.push_back(
935 GURL("data:text/html:base64,"));
936 url_chain.push_back(
937 GURL("data:text/html:base64,blahblahblah"));
938 url_chain.push_back(
939 GURL("data:application/octet-stream:base64,blahblah"));
940 GURL referrer("data:text/html:base64,foobar");
941 std::string hash = "hash";
943 content::MockDownloadItem item;
944 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
945 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
946 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
947 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
948 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
949 EXPECT_CALL(item, GetTabReferrerUrl())
950 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
951 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
952 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
953 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
954 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
956 EXPECT_CALL(*sb_service_->mock_database_manager(),
957 MatchDownloadWhitelistUrl(_)).WillRepeatedly(Return(false));
958 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
959 .Times(1);
960 EXPECT_CALL(*binary_feature_extractor_.get(),
961 ExtractImageFeatures(
962 a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _))
963 .Times(1);
965 download_service_->CheckClientDownload(
966 &item,
967 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
968 base::Unretained(this)));
969 MessageLoop::current()->Run();
971 #if defined(OS_WIN) || defined(OS_MACOSX)
972 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
973 ASSERT_TRUE(HasClientDownloadRequest());
974 const ClientDownloadRequest& request = *GetClientDownloadRequest();
975 const char kExpectedUrl[] =
976 "data:application/octet-stream:base64,"
977 "ACBF6DFC6F907662F566CA0241DFE8690C48661F440BA1BBD0B86C582845CCC8";
978 const char kExpectedRedirect1[] = "data:text/html:base64,";
979 const char kExpectedRedirect2[] =
980 "data:text/html:base64,"
981 "620680767E15717A57DB11D94D1BEBD32B3344EBC5994DF4FB07B0D473F4EF6B";
982 const char kExpectedReferrer[] =
983 "data:text/html:base64,"
984 "06E2C655B9F7130B508FFF86FD19B57E6BF1A1CFEFD6EFE1C3EB09FE24EF456A";
985 EXPECT_EQ(hash, request.digests().sha256());
986 EXPECT_EQ(kExpectedUrl, request.url());
987 EXPECT_EQ(3, request.resources_size());
988 EXPECT_TRUE(RequestContainsResource(request,
989 ClientDownloadRequest::DOWNLOAD_REDIRECT,
990 kExpectedRedirect1, ""));
991 EXPECT_TRUE(RequestContainsResource(request,
992 ClientDownloadRequest::DOWNLOAD_REDIRECT,
993 kExpectedRedirect2, ""));
994 EXPECT_TRUE(RequestContainsResource(request,
995 ClientDownloadRequest::DOWNLOAD_URL,
996 kExpectedUrl, kExpectedReferrer));
997 ClearClientDownloadRequest();
998 #else
999 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1000 EXPECT_FALSE(HasClientDownloadRequest());
1001 #endif
1004 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadZip) {
1005 ClientDownloadResponse response;
1006 response.set_verdict(ClientDownloadResponse::SAFE);
1007 net::FakeURLFetcherFactory factory(NULL);
1008 // Empty response means SAFE.
1009 factory.SetFakeResponse(
1010 DownloadProtectionService::GetDownloadRequestUrl(),
1011 response.SerializeAsString(),
1012 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
1014 base::ScopedTempDir download_dir;
1015 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
1017 base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp")));
1018 base::FilePath a_zip(FILE_PATH_LITERAL("a.zip"));
1019 std::vector<GURL> url_chain;
1020 url_chain.push_back(GURL("http://www.evil.com/a.zip"));
1021 GURL referrer("http://www.google.com/");
1022 std::string hash = "hash";
1024 content::MockDownloadItem item;
1025 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
1026 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
1027 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1028 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1029 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1030 EXPECT_CALL(item, GetTabReferrerUrl())
1031 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1032 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1033 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1034 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1035 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1037 // Write out a zip archive to the temporary file. In this case, it
1038 // only contains a text file.
1039 base::ScopedTempDir zip_source_dir;
1040 ASSERT_TRUE(zip_source_dir.CreateUniqueTempDir());
1041 std::string file_contents = "dummy file";
1042 ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
1043 zip_source_dir.path().Append(FILE_PATH_LITERAL("file.txt")),
1044 file_contents.data(), file_contents.size()));
1045 ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false));
1047 download_service_->CheckClientDownload(
1048 &item,
1049 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1050 base::Unretained(this)));
1051 MessageLoop::current()->Run();
1052 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1053 EXPECT_FALSE(HasClientDownloadRequest());
1054 Mock::VerifyAndClearExpectations(sb_service_.get());
1055 Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
1057 // Now check with an executable in the zip file as well.
1058 ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
1059 zip_source_dir.path().Append(FILE_PATH_LITERAL("file.exe")),
1060 file_contents.data(), file_contents.size()));
1061 ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false));
1063 EXPECT_CALL(*sb_service_->mock_database_manager(),
1064 MatchDownloadWhitelistUrl(_))
1065 .WillRepeatedly(Return(false));
1067 download_service_->CheckClientDownload(
1068 &item,
1069 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1070 base::Unretained(this)));
1071 MessageLoop::current()->Run();
1073 #if defined(OS_WIN) || defined(OS_MACOSX)
1074 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1075 EXPECT_TRUE(HasClientDownloadRequest());
1076 const ClientDownloadRequest& request = *GetClientDownloadRequest();
1077 EXPECT_EQ(1, request.archived_binary_size());
1078 const ClientDownloadRequest_ArchivedBinary* archived_binary =
1079 GetRequestArchivedBinary(request, "file.exe");
1080 ASSERT_NE(nullptr, archived_binary);
1081 EXPECT_EQ(ClientDownloadRequest_DownloadType_WIN_EXECUTABLE,
1082 archived_binary->download_type());
1083 EXPECT_EQ(static_cast<int64_t>(file_contents.size()),
1084 archived_binary->length());
1085 ClearClientDownloadRequest();
1086 #else
1087 // For !(OS_WIN || OS_MACOSX), no file types are currently supported. Hence
1088 // the resulting verdict is UNKNOWN.
1089 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1090 EXPECT_FALSE(HasClientDownloadRequest());
1091 #endif
1092 Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
1094 // If the response is dangerous the result should also be marked as
1095 // dangerous.
1096 response.set_verdict(ClientDownloadResponse::DANGEROUS);
1097 factory.SetFakeResponse(
1098 DownloadProtectionService::GetDownloadRequestUrl(),
1099 response.SerializeAsString(),
1100 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
1102 download_service_->CheckClientDownload(
1103 &item,
1104 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1105 base::Unretained(this)));
1106 MessageLoop::current()->Run();
1108 #if defined(OS_WIN) || defined(OS_MACOSX)
1109 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
1110 EXPECT_TRUE(HasClientDownloadRequest());
1111 ClearClientDownloadRequest();
1112 #else
1113 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1114 EXPECT_FALSE(HasClientDownloadRequest());
1115 #endif
1116 Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
1119 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadCorruptZip) {
1120 base::ScopedTempDir download_dir;
1121 ASSERT_TRUE(download_dir.CreateUniqueTempDir());
1123 base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp")));
1124 base::FilePath a_zip(FILE_PATH_LITERAL("a.zip"));
1125 std::vector<GURL> url_chain;
1126 url_chain.push_back(GURL("http://www.evil.com/a.zip"));
1127 GURL referrer("http://www.google.com/");
1128 std::string hash = "hash";
1130 content::MockDownloadItem item;
1131 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
1132 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
1133 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1134 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1135 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1136 EXPECT_CALL(item, GetTabReferrerUrl())
1137 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1138 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1139 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1140 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1141 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1143 std::string file_contents = "corrupt zip file";
1144 ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
1145 a_tmp, file_contents.data(), file_contents.size()));
1147 download_service_->CheckClientDownload(
1148 &item,
1149 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1150 base::Unretained(this)));
1151 MessageLoop::current()->Run();
1152 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1153 EXPECT_FALSE(HasClientDownloadRequest());
1154 Mock::VerifyAndClearExpectations(sb_service_.get());
1155 Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
1158 TEST_F(DownloadProtectionServiceTest, CheckClientCrxDownloadSuccess) {
1159 ClientDownloadResponse response;
1160 // Even if the server verdict is dangerous we should return SAFE because
1161 // DownloadProtectionService::IsSupportedDownload() will return false
1162 // for crx downloads.
1163 response.set_verdict(ClientDownloadResponse::DANGEROUS);
1164 net::FakeURLFetcherFactory factory(NULL);
1165 // Empty response means SAFE.
1166 factory.SetFakeResponse(
1167 DownloadProtectionService::GetDownloadRequestUrl(),
1168 response.SerializeAsString(),
1169 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
1171 base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
1172 base::FilePath a_crx(FILE_PATH_LITERAL("a.crx"));
1173 std::vector<GURL> url_chain;
1174 url_chain.push_back(GURL("http://www.evil.com/a.crx"));
1175 GURL referrer("http://www.google.com/");
1176 std::string hash = "hash";
1178 content::MockDownloadItem item;
1179 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
1180 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_crx));
1181 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1182 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1183 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1184 EXPECT_CALL(item, GetTabReferrerUrl())
1185 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1186 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1187 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1188 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1189 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1191 EXPECT_CALL(*sb_service_->mock_database_manager(),
1192 MatchDownloadWhitelistUrl(_))
1193 .WillRepeatedly(Return(false));
1194 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
1195 .Times(1);
1196 EXPECT_CALL(*binary_feature_extractor_.get(),
1197 ExtractImageFeatures(
1198 a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _))
1199 .Times(1);
1201 EXPECT_FALSE(download_service_->IsSupportedDownload(item, a_crx));
1202 download_service_->CheckClientDownload(
1203 &item,
1204 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1205 base::Unretained(this)));
1206 MessageLoop::current()->Run();
1207 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1210 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadValidateRequest) {
1211 net::TestURLFetcherFactory factory;
1213 base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1214 base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1215 std::vector<GURL> url_chain;
1216 url_chain.push_back(GURL("http://www.google.com/"));
1217 url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1218 GURL referrer("http://www.google.com/");
1219 std::string hash = "hash";
1220 std::string remote_address = "10.11.12.13";
1222 content::MockDownloadItem item;
1223 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1224 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1225 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1226 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1227 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1228 EXPECT_CALL(item, GetTabReferrerUrl())
1229 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1230 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1231 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1232 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1233 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1235 EXPECT_CALL(*sb_service_->mock_database_manager(),
1236 MatchDownloadWhitelistUrl(_))
1237 .WillRepeatedly(Return(false));
1238 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
1239 .WillOnce(SetCertificateContents("dummy cert data"));
1240 EXPECT_CALL(
1241 *binary_feature_extractor_.get(),
1242 ExtractImageFeatures(tmp_path, BinaryFeatureExtractor::kDefaultOptions,
1243 _, _))
1244 .WillOnce(SetDosHeaderContents("dummy dos header"));
1245 download_service_->CheckClientDownload(
1246 &item,
1247 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1248 base::Unretained(this)));
1250 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1251 // SendRequest is not called. Wait for FinishRequest to call our callback.
1252 MessageLoop::current()->Run();
1253 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1254 EXPECT_EQ(NULL, fetcher);
1255 EXPECT_FALSE(HasClientDownloadRequest());
1256 #else
1257 // Run the message loop(s) until SendRequest is called.
1258 FlushThreadMessageLoops();
1259 EXPECT_TRUE(HasClientDownloadRequest());
1260 ClearClientDownloadRequest();
1261 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1262 ASSERT_TRUE(fetcher);
1263 ClientDownloadRequest request;
1264 EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1265 EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1266 EXPECT_EQ(hash, request.digests().sha256());
1267 EXPECT_EQ(item.GetReceivedBytes(), request.length());
1268 EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1269 EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1270 EXPECT_EQ(2, request.resources_size());
1271 EXPECT_TRUE(RequestContainsResource(request,
1272 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1273 "http://www.google.com/", ""));
1274 EXPECT_TRUE(RequestContainsResource(request,
1275 ClientDownloadRequest::DOWNLOAD_URL,
1276 "http://www.google.com/bla.exe",
1277 referrer.spec()));
1278 EXPECT_TRUE(request.has_signature());
1279 ASSERT_EQ(1, request.signature().certificate_chain_size());
1280 const ClientDownloadRequest_CertificateChain& chain =
1281 request.signature().certificate_chain(0);
1282 ASSERT_EQ(1, chain.element_size());
1283 EXPECT_EQ("dummy cert data", chain.element(0).certificate());
1284 EXPECT_TRUE(request.has_image_headers());
1285 const ClientDownloadRequest_ImageHeaders& headers =
1286 request.image_headers();
1287 EXPECT_TRUE(headers.has_pe_headers());
1288 EXPECT_TRUE(headers.pe_headers().has_dos_header());
1289 EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
1291 // Simulate the request finishing.
1292 base::MessageLoop::current()->PostTask(
1293 FROM_HERE,
1294 base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1295 base::Unretained(this), fetcher));
1296 MessageLoop::current()->Run();
1297 #endif
1300 // Similar to above, but with an unsigned binary.
1301 TEST_F(DownloadProtectionServiceTest,
1302 CheckClientDownloadValidateRequestNoSignature) {
1303 net::TestURLFetcherFactory factory;
1305 base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1306 base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1307 std::vector<GURL> url_chain;
1308 url_chain.push_back(GURL("http://www.google.com/"));
1309 url_chain.push_back(GURL("ftp://www.google.com/bla.exe"));
1310 GURL referrer("http://www.google.com/");
1311 std::string hash = "hash";
1312 std::string remote_address = "10.11.12.13";
1314 content::MockDownloadItem item;
1315 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1316 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1317 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1318 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1319 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1320 EXPECT_CALL(item, GetTabReferrerUrl())
1321 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1322 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1323 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1324 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1325 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1327 EXPECT_CALL(*sb_service_->mock_database_manager(),
1328 MatchDownloadWhitelistUrl(_))
1329 .WillRepeatedly(Return(false));
1330 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1331 EXPECT_CALL(*binary_feature_extractor_.get(),
1332 ExtractImageFeatures(tmp_path,
1333 BinaryFeatureExtractor::kDefaultOptions,
1334 _, _));
1335 download_service_->CheckClientDownload(
1336 &item,
1337 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1338 base::Unretained(this)));
1340 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1341 // SendRequest is not called. Wait for FinishRequest to call our callback.
1342 MessageLoop::current()->Run();
1343 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1344 EXPECT_EQ(NULL, fetcher);
1345 EXPECT_FALSE(HasClientDownloadRequest());
1346 #else
1347 // Run the message loop(s) until SendRequest is called.
1348 FlushThreadMessageLoops();
1349 EXPECT_TRUE(HasClientDownloadRequest());
1350 ClearClientDownloadRequest();
1351 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1352 ASSERT_TRUE(fetcher);
1353 ClientDownloadRequest request;
1354 EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1355 EXPECT_EQ("ftp://www.google.com/bla.exe", request.url());
1356 EXPECT_EQ(hash, request.digests().sha256());
1357 EXPECT_EQ(item.GetReceivedBytes(), request.length());
1358 EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1359 EXPECT_EQ(2, request.resources_size());
1360 EXPECT_TRUE(RequestContainsResource(request,
1361 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1362 "http://www.google.com/", ""));
1363 EXPECT_TRUE(RequestContainsResource(request,
1364 ClientDownloadRequest::DOWNLOAD_URL,
1365 "ftp://www.google.com/bla.exe",
1366 referrer.spec()));
1367 EXPECT_TRUE(request.has_signature());
1368 EXPECT_EQ(0, request.signature().certificate_chain_size());
1370 // Simulate the request finishing.
1371 base::MessageLoop::current()->PostTask(
1372 FROM_HERE,
1373 base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1374 base::Unretained(this), fetcher));
1375 MessageLoop::current()->Run();
1376 #endif
1379 // Similar to above, but with tab history.
1380 TEST_F(DownloadProtectionServiceTest,
1381 CheckClientDownloadValidateRequestTabHistory) {
1382 net::TestURLFetcherFactory factory;
1384 base::ScopedTempDir profile_dir;
1385 ASSERT_TRUE(profile_dir.CreateUniqueTempDir());
1386 TestingProfile profile(profile_dir.path());
1387 ASSERT_TRUE(
1388 profile.CreateHistoryService(true /* delete_file */, false /* no_db */));
1390 base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1391 base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1392 std::vector<GURL> url_chain;
1393 url_chain.push_back(GURL("http://www.google.com/"));
1394 url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1395 GURL referrer("http://www.google.com/");
1396 GURL tab_url("http://tab.com/final");
1397 GURL tab_referrer("http://tab.com/referrer");
1398 std::string hash = "hash";
1399 std::string remote_address = "10.11.12.13";
1401 content::MockDownloadItem item;
1402 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1403 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1404 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1405 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1406 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
1407 EXPECT_CALL(item, GetTabReferrerUrl())
1408 .WillRepeatedly(ReturnRef(tab_referrer));
1409 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1410 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1411 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1412 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1413 EXPECT_CALL(item, GetBrowserContext()).WillRepeatedly(Return(&profile));
1414 EXPECT_CALL(*sb_service_->mock_database_manager(),
1415 MatchDownloadWhitelistUrl(_))
1416 .WillRepeatedly(Return(false));
1417 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
1418 .WillRepeatedly(SetCertificateContents("dummy cert data"));
1419 EXPECT_CALL(
1420 *binary_feature_extractor_.get(),
1421 ExtractImageFeatures(tmp_path, BinaryFeatureExtractor::kDefaultOptions,
1422 _, _))
1423 .WillRepeatedly(SetDosHeaderContents("dummy dos header"));
1425 // First test with no history match for the tab URL.
1427 TestURLFetcherWatcher fetcher_watcher(&factory);
1428 download_service_->CheckClientDownload(
1429 &item,
1430 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1431 base::Unretained(this)));
1433 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1434 // SendRequest is not called. Wait for FinishRequest to call our callback.
1435 MessageLoop::current()->Run();
1436 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1437 EXPECT_EQ(NULL, fetcher);
1438 EXPECT_FALSE(HasClientDownloadRequest());
1439 #else
1440 EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
1441 EXPECT_TRUE(HasClientDownloadRequest());
1442 ClearClientDownloadRequest();
1443 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1444 ASSERT_TRUE(fetcher);
1445 ClientDownloadRequest request;
1446 EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1447 EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1448 EXPECT_EQ(hash, request.digests().sha256());
1449 EXPECT_EQ(item.GetReceivedBytes(), request.length());
1450 EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1451 EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1452 EXPECT_EQ(3, request.resources_size());
1453 EXPECT_TRUE(
1454 RequestContainsResource(request,
1455 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1456 "http://www.google.com/",
1457 ""));
1458 EXPECT_TRUE(RequestContainsResource(request,
1459 ClientDownloadRequest::DOWNLOAD_URL,
1460 "http://www.google.com/bla.exe",
1461 referrer.spec()));
1462 EXPECT_TRUE(RequestContainsResource(request,
1463 ClientDownloadRequest::TAB_URL,
1464 tab_url.spec(),
1465 tab_referrer.spec()));
1466 EXPECT_TRUE(request.has_signature());
1467 ASSERT_EQ(1, request.signature().certificate_chain_size());
1468 const ClientDownloadRequest_CertificateChain& chain =
1469 request.signature().certificate_chain(0);
1470 ASSERT_EQ(1, chain.element_size());
1471 EXPECT_EQ("dummy cert data", chain.element(0).certificate());
1472 EXPECT_TRUE(request.has_image_headers());
1473 const ClientDownloadRequest_ImageHeaders& headers =
1474 request.image_headers();
1475 EXPECT_TRUE(headers.has_pe_headers());
1476 EXPECT_TRUE(headers.pe_headers().has_dos_header());
1477 EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
1479 // Simulate the request finishing.
1480 base::MessageLoop::current()->PostTask(
1481 FROM_HERE,
1482 base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1483 base::Unretained(this),
1484 fetcher));
1485 MessageLoop::current()->Run();
1486 #endif
1489 // Now try with a history match.
1491 history::RedirectList redirects;
1492 redirects.push_back(GURL("http://tab.com/ref1"));
1493 redirects.push_back(GURL("http://tab.com/ref2"));
1494 redirects.push_back(tab_url);
1495 HistoryServiceFactory::GetForProfile(&profile,
1496 ServiceAccessType::EXPLICIT_ACCESS)
1497 ->AddPage(tab_url,
1498 base::Time::Now(),
1499 reinterpret_cast<history::ContextID>(1),
1501 GURL(),
1502 redirects,
1503 ui::PAGE_TRANSITION_TYPED,
1504 history::SOURCE_BROWSED,
1505 false);
1507 TestURLFetcherWatcher fetcher_watcher(&factory);
1508 download_service_->CheckClientDownload(
1509 &item,
1510 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1511 base::Unretained(this)));
1512 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1513 // SendRequest is not called. Wait for FinishRequest to call our callback.
1514 MessageLoop::current()->Run();
1515 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1516 EXPECT_EQ(NULL, fetcher);
1517 EXPECT_FALSE(HasClientDownloadRequest());
1518 #else
1519 EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
1520 EXPECT_TRUE(HasClientDownloadRequest());
1521 ClearClientDownloadRequest();
1522 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1523 ASSERT_TRUE(fetcher);
1524 ClientDownloadRequest request;
1525 EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1526 EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1527 EXPECT_EQ(hash, request.digests().sha256());
1528 EXPECT_EQ(item.GetReceivedBytes(), request.length());
1529 EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1530 EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1531 EXPECT_EQ(5, request.resources_size());
1532 EXPECT_TRUE(
1533 RequestContainsResource(request,
1534 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1535 "http://www.google.com/",
1536 ""));
1537 EXPECT_TRUE(RequestContainsResource(request,
1538 ClientDownloadRequest::DOWNLOAD_URL,
1539 "http://www.google.com/bla.exe",
1540 referrer.spec()));
1541 EXPECT_TRUE(RequestContainsResource(request,
1542 ClientDownloadRequest::TAB_REDIRECT,
1543 "http://tab.com/ref1",
1544 ""));
1545 EXPECT_TRUE(RequestContainsResource(request,
1546 ClientDownloadRequest::TAB_REDIRECT,
1547 "http://tab.com/ref2",
1548 ""));
1549 EXPECT_TRUE(RequestContainsResource(request,
1550 ClientDownloadRequest::TAB_URL,
1551 tab_url.spec(),
1552 tab_referrer.spec()));
1553 EXPECT_TRUE(request.has_signature());
1554 ASSERT_EQ(1, request.signature().certificate_chain_size());
1555 const ClientDownloadRequest_CertificateChain& chain =
1556 request.signature().certificate_chain(0);
1557 ASSERT_EQ(1, chain.element_size());
1558 EXPECT_EQ("dummy cert data", chain.element(0).certificate());
1560 // Simulate the request finishing.
1561 base::MessageLoop::current()->PostTask(
1562 FROM_HERE,
1563 base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1564 base::Unretained(this),
1565 fetcher));
1566 MessageLoop::current()->Run();
1567 #endif
1571 TEST_F(DownloadProtectionServiceTest, TestCheckDownloadUrl) {
1572 std::vector<GURL> url_chain;
1573 url_chain.push_back(GURL("http://www.google.com/"));
1574 url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1575 GURL referrer("http://www.google.com/");
1576 std::string hash = "hash";
1578 content::MockDownloadItem item;
1579 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1580 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1581 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1583 // CheckDownloadURL returns immediately which means the client object callback
1584 // will never be called. Nevertheless the callback provided to
1585 // CheckClientDownload must still be called.
1586 EXPECT_CALL(*sb_service_->mock_database_manager(),
1587 CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1588 .WillOnce(Return(true));
1589 download_service_->CheckDownloadUrl(
1590 item,
1591 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1592 base::Unretained(this)));
1593 MessageLoop::current()->Run();
1594 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1595 Mock::VerifyAndClearExpectations(sb_service_.get());
1597 EXPECT_CALL(*sb_service_->mock_database_manager(),
1598 CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1599 .WillOnce(DoAll(CheckDownloadUrlDone(SB_THREAT_TYPE_SAFE),
1600 Return(false)));
1601 download_service_->CheckDownloadUrl(
1602 item,
1603 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1604 base::Unretained(this)));
1605 MessageLoop::current()->Run();
1606 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1607 Mock::VerifyAndClearExpectations(sb_service_.get());
1609 EXPECT_CALL(*sb_service_->mock_database_manager(),
1610 CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1611 .WillOnce(DoAll(
1612 CheckDownloadUrlDone(SB_THREAT_TYPE_URL_MALWARE),
1613 Return(false)));
1614 download_service_->CheckDownloadUrl(
1615 item,
1616 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1617 base::Unretained(this)));
1618 MessageLoop::current()->Run();
1619 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1620 Mock::VerifyAndClearExpectations(sb_service_.get());
1622 EXPECT_CALL(*sb_service_->mock_database_manager(),
1623 CheckDownloadUrl(ContainerEq(url_chain),
1624 NotNull()))
1625 .WillOnce(DoAll(
1626 CheckDownloadUrlDone(SB_THREAT_TYPE_BINARY_MALWARE_URL),
1627 Return(false)));
1628 download_service_->CheckDownloadUrl(
1629 item,
1630 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1631 base::Unretained(this)));
1632 MessageLoop::current()->Run();
1633 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
1636 TEST_F(DownloadProtectionServiceTest, TestDownloadRequestTimeout) {
1637 net::TestURLFetcherFactory factory;
1639 std::vector<GURL> url_chain;
1640 url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1641 GURL referrer("http://www.google.com/");
1642 base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1643 base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1644 std::string hash = "hash";
1646 content::MockDownloadItem item;
1647 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1648 EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1649 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1650 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1651 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1652 EXPECT_CALL(item, GetTabReferrerUrl())
1653 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1654 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1655 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1656 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1657 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1659 EXPECT_CALL(*sb_service_->mock_database_manager(),
1660 MatchDownloadWhitelistUrl(_))
1661 .WillRepeatedly(Return(false));
1662 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1663 EXPECT_CALL(*binary_feature_extractor_.get(),
1664 ExtractImageFeatures(tmp_path,
1665 BinaryFeatureExtractor::kDefaultOptions,
1666 _, _));
1668 download_service_->download_request_timeout_ms_ = 10;
1669 download_service_->CheckClientDownload(
1670 &item,
1671 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1672 base::Unretained(this)));
1674 // The request should time out because the HTTP request hasn't returned
1675 // anything yet.
1676 MessageLoop::current()->Run();
1677 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1678 #if defined(OS_WIN) || defined(OS_MACOSX)
1679 EXPECT_TRUE(HasClientDownloadRequest());
1680 ClearClientDownloadRequest();
1681 #else
1682 EXPECT_FALSE(HasClientDownloadRequest());
1683 #endif
1686 TEST_F(DownloadProtectionServiceTest, TestDownloadItemDestroyed) {
1687 net::TestURLFetcherFactory factory;
1689 std::vector<GURL> url_chain;
1690 url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1691 GURL referrer("http://www.google.com/");
1692 GURL tab_url("http://www.google.com/tab");
1693 base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1694 base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1695 std::string hash = "hash";
1698 content::MockDownloadItem item;
1699 EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1700 EXPECT_CALL(item, GetTargetFilePath())
1701 .WillRepeatedly(ReturnRef(final_path));
1702 EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1703 EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1704 EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
1705 EXPECT_CALL(item, GetTabReferrerUrl())
1706 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1707 EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1708 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1709 EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1710 EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1712 EXPECT_CALL(*sb_service_->mock_database_manager(),
1713 MatchDownloadWhitelistUrl(_))
1714 .WillRepeatedly(Return(false));
1715 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1716 EXPECT_CALL(*binary_feature_extractor_.get(),
1717 ExtractImageFeatures(
1718 tmp_path, BinaryFeatureExtractor::kDefaultOptions, _, _));
1720 download_service_->CheckClientDownload(
1721 &item,
1722 base::Bind(&DownloadProtectionServiceTest::SyncCheckDoneCallback,
1723 base::Unretained(this)));
1724 // MockDownloadItem going out of scope triggers the OnDownloadDestroyed
1725 // notification.
1728 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1729 EXPECT_FALSE(HasClientDownloadRequest());
1732 TEST_F(DownloadProtectionServiceTest,
1733 TestDownloadItemDestroyedDuringWhitelistCheck) {
1734 net::TestURLFetcherFactory factory;
1736 std::vector<GURL> url_chain;
1737 url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1738 GURL referrer("http://www.google.com/");
1739 GURL tab_url("http://www.google.com/tab");
1740 base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1741 base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1742 std::string hash = "hash";
1744 scoped_ptr<content::MockDownloadItem> item(new content::MockDownloadItem);
1745 EXPECT_CALL(*item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1746 EXPECT_CALL(*item, GetTargetFilePath())
1747 .WillRepeatedly(ReturnRef(final_path));
1748 EXPECT_CALL(*item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1749 EXPECT_CALL(*item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1750 EXPECT_CALL(*item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
1751 EXPECT_CALL(*item, GetTabReferrerUrl())
1752 .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1753 EXPECT_CALL(*item, GetHash()).WillRepeatedly(ReturnRef(hash));
1754 EXPECT_CALL(*item, GetReceivedBytes()).WillRepeatedly(Return(100));
1755 EXPECT_CALL(*item, HasUserGesture()).WillRepeatedly(Return(true));
1756 EXPECT_CALL(*item, GetRemoteAddress()).WillRepeatedly(Return(""));
1758 EXPECT_CALL(*sb_service_->mock_database_manager(),
1759 MatchDownloadWhitelistUrl(_))
1760 .WillRepeatedly(Invoke([&item](const GURL&) {
1761 item.reset();
1762 return false;
1763 }));
1764 EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1765 EXPECT_CALL(*binary_feature_extractor_.get(),
1766 ExtractImageFeatures(tmp_path,
1767 BinaryFeatureExtractor::kDefaultOptions,
1768 _, _));
1770 download_service_->CheckClientDownload(
1771 item.get(),
1772 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1773 base::Unretained(this)));
1775 MessageLoop::current()->Run();
1776 EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1777 EXPECT_FALSE(HasClientDownloadRequest());
1780 TEST_F(DownloadProtectionServiceTest, GetCertificateWhitelistStrings) {
1781 // We'll pass this cert in as the "issuer", even though it isn't really
1782 // used to sign the certs below. GetCertificateWhitelistStirngs doesn't care
1783 // about this.
1784 scoped_refptr<net::X509Certificate> issuer_cert(
1785 ReadTestCertificate("issuer.pem"));
1786 ASSERT_TRUE(issuer_cert.get());
1787 std::string cert_base = "cert/" + base::HexEncode(
1788 issuer_cert->fingerprint().data,
1789 sizeof(issuer_cert->fingerprint().data));
1791 scoped_refptr<net::X509Certificate> cert(ReadTestCertificate("test_cn.pem"));
1792 ASSERT_TRUE(cert.get());
1793 std::vector<std::string> whitelist_strings;
1794 GetCertificateWhitelistStrings(
1795 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1796 // This also tests escaping of characters in the certificate attributes.
1797 EXPECT_THAT(whitelist_strings, ElementsAre(
1798 cert_base + "/CN=subject%2F%251"));
1800 cert = ReadTestCertificate("test_cn_o.pem");
1801 ASSERT_TRUE(cert.get());
1802 whitelist_strings.clear();
1803 GetCertificateWhitelistStrings(
1804 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1805 EXPECT_THAT(whitelist_strings,
1806 ElementsAre(cert_base + "/CN=subject",
1807 cert_base + "/CN=subject/O=org",
1808 cert_base + "/O=org"));
1810 cert = ReadTestCertificate("test_cn_o_ou.pem");
1811 ASSERT_TRUE(cert.get());
1812 whitelist_strings.clear();
1813 GetCertificateWhitelistStrings(
1814 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1815 EXPECT_THAT(whitelist_strings,
1816 ElementsAre(cert_base + "/CN=subject",
1817 cert_base + "/CN=subject/O=org",
1818 cert_base + "/CN=subject/O=org/OU=unit",
1819 cert_base + "/CN=subject/OU=unit",
1820 cert_base + "/O=org",
1821 cert_base + "/O=org/OU=unit",
1822 cert_base + "/OU=unit"));
1824 cert = ReadTestCertificate("test_cn_ou.pem");
1825 ASSERT_TRUE(cert.get());
1826 whitelist_strings.clear();
1827 GetCertificateWhitelistStrings(
1828 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1829 EXPECT_THAT(whitelist_strings,
1830 ElementsAre(cert_base + "/CN=subject",
1831 cert_base + "/CN=subject/OU=unit",
1832 cert_base + "/OU=unit"));
1834 cert = ReadTestCertificate("test_o.pem");
1835 ASSERT_TRUE(cert.get());
1836 whitelist_strings.clear();
1837 GetCertificateWhitelistStrings(
1838 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1839 EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/O=org"));
1841 cert = ReadTestCertificate("test_o_ou.pem");
1842 ASSERT_TRUE(cert.get());
1843 whitelist_strings.clear();
1844 GetCertificateWhitelistStrings(
1845 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1846 EXPECT_THAT(whitelist_strings,
1847 ElementsAre(cert_base + "/O=org",
1848 cert_base + "/O=org/OU=unit",
1849 cert_base + "/OU=unit"));
1851 cert = ReadTestCertificate("test_ou.pem");
1852 ASSERT_TRUE(cert.get());
1853 whitelist_strings.clear();
1854 GetCertificateWhitelistStrings(
1855 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1856 EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/OU=unit"));
1858 cert = ReadTestCertificate("test_c.pem");
1859 ASSERT_TRUE(cert.get());
1860 whitelist_strings.clear();
1861 GetCertificateWhitelistStrings(
1862 *cert.get(), *issuer_cert.get(), &whitelist_strings);
1863 EXPECT_THAT(whitelist_strings, ElementsAre());
1866 namespace {
1868 class MockPageNavigator : public content::PageNavigator {
1869 public:
1870 MOCK_METHOD1(OpenURL, content::WebContents*(const content::OpenURLParams&));
1873 // A custom matcher that matches a OpenURLParams value with a url with a query
1874 // parameter patching |value|.
1875 MATCHER_P(OpenURLParamsWithContextValue, value, "") {
1876 std::string query_value;
1877 return net::GetValueForKeyInQuery(arg.url, "ctx", &query_value) &&
1878 query_value == value;
1881 } // namespace
1883 // ShowDetailsForDownload() should open a URL showing more information about why
1884 // a download was flagged by SafeBrowsing. The URL should have a &ctx= parameter
1885 // whose value is the DownloadDangerType.
1886 TEST_F(DownloadProtectionServiceTest, ShowDetailsForDownloadHasContext) {
1887 StrictMock<MockPageNavigator> mock_page_navigator;
1888 StrictMock<content::MockDownloadItem> mock_download_item;
1890 EXPECT_CALL(mock_download_item, GetDangerType())
1891 .WillOnce(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST));
1892 EXPECT_CALL(mock_page_navigator, OpenURL(OpenURLParamsWithContextValue("7")));
1894 download_service_->ShowDetailsForDownload(mock_download_item,
1895 &mock_page_navigator);
1898 } // namespace safe_browsing