• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/safe_browsing/download_protection_service.h"
6 
7 #include <map>
8 #include <string>
9 
10 #include "base/base_paths.h"
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/file_util.h"
14 #include "base/files/file_path.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/path_service.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/threading/sequenced_worker_pool.h"
23 #include "chrome/browser/history/history_service.h"
24 #include "chrome/browser/history/history_service_factory.h"
25 #include "chrome/browser/safe_browsing/binary_feature_extractor.h"
26 #include "chrome/browser/safe_browsing/database_manager.h"
27 #include "chrome/browser/safe_browsing/download_feedback_service.h"
28 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
29 #include "chrome/common/safe_browsing/csd.pb.h"
30 #include "chrome/test/base/testing_profile.h"
31 #include "content/public/test/mock_download_item.h"
32 #include "content/public/test/test_browser_thread_bundle.h"
33 #include "content/public/test/test_utils.h"
34 #include "net/cert/x509_certificate.h"
35 #include "net/http/http_status_code.h"
36 #include "net/url_request/test_url_fetcher_factory.h"
37 #include "net/url_request/url_fetcher_delegate.h"
38 #include "net/url_request/url_request_status.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/gtest/include/gtest/gtest.h"
41 #include "third_party/zlib/google/zip.h"
42 #include "url/gurl.h"
43 
44 using ::testing::Assign;
45 using ::testing::ContainerEq;
46 using ::testing::DoAll;
47 using ::testing::ElementsAre;
48 using ::testing::Mock;
49 using ::testing::NotNull;
50 using ::testing::Return;
51 using ::testing::ReturnRef;
52 using ::testing::SaveArg;
53 using ::testing::StrictMock;
54 using ::testing::_;
55 using base::MessageLoop;
56 using content::BrowserThread;
57 namespace safe_browsing {
58 namespace {
59 // A SafeBrowsingDatabaseManager implementation that returns a fixed result for
60 // a given URL.
61 class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager {
62  public:
MockSafeBrowsingDatabaseManager(SafeBrowsingService * service)63   explicit MockSafeBrowsingDatabaseManager(SafeBrowsingService* service)
64       : SafeBrowsingDatabaseManager(service) { }
65 
66   MOCK_METHOD1(MatchDownloadWhitelistUrl, bool(const GURL&));
67   MOCK_METHOD1(MatchDownloadWhitelistString, bool(const std::string&));
68   MOCK_METHOD2(CheckDownloadUrl, bool(
69       const std::vector<GURL>& url_chain,
70       SafeBrowsingDatabaseManager::Client* client));
71 
72  private:
~MockSafeBrowsingDatabaseManager()73   virtual ~MockSafeBrowsingDatabaseManager() {}
74   DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager);
75 };
76 
77 class FakeSafeBrowsingService : public SafeBrowsingService {
78  public:
FakeSafeBrowsingService()79   FakeSafeBrowsingService() { }
80 
81   // Returned pointer has the same lifespan as the database_manager_ refcounted
82   // object.
mock_database_manager()83   MockSafeBrowsingDatabaseManager* mock_database_manager() {
84     return mock_database_manager_;
85   }
86 
87  protected:
~FakeSafeBrowsingService()88   virtual ~FakeSafeBrowsingService() { }
89 
CreateDatabaseManager()90   virtual SafeBrowsingDatabaseManager* CreateDatabaseManager() OVERRIDE {
91     mock_database_manager_ = new MockSafeBrowsingDatabaseManager(this);
92     return mock_database_manager_;
93   }
94 
95  private:
96   MockSafeBrowsingDatabaseManager* mock_database_manager_;
97 
98   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
99 };
100 
101 class MockBinaryFeatureExtractor : public BinaryFeatureExtractor {
102  public:
MockBinaryFeatureExtractor()103   MockBinaryFeatureExtractor() {}
104   MOCK_METHOD2(CheckSignature, void(const base::FilePath&,
105                                     ClientDownloadRequest_SignatureInfo*));
106   MOCK_METHOD2(ExtractImageHeaders, void(const base::FilePath&,
107                                          ClientDownloadRequest_ImageHeaders*));
108 
109  protected:
~MockBinaryFeatureExtractor()110   virtual ~MockBinaryFeatureExtractor() {}
111 
112  private:
113   DISALLOW_COPY_AND_ASSIGN(MockBinaryFeatureExtractor);
114 };
115 
116 class TestURLFetcherWatcher : public net::TestURLFetcherDelegateForTests {
117  public:
TestURLFetcherWatcher(net::TestURLFetcherFactory * factory)118   explicit TestURLFetcherWatcher(net::TestURLFetcherFactory* factory)
119       : factory_(factory), fetcher_id_(-1) {
120     factory_->SetDelegateForTests(this);
121   }
~TestURLFetcherWatcher()122   ~TestURLFetcherWatcher() {
123     factory_->SetDelegateForTests(NULL);
124   }
125 
126   // TestURLFetcherDelegateForTests impl:
OnRequestStart(int fetcher_id)127   virtual void OnRequestStart(int fetcher_id) OVERRIDE {
128     fetcher_id_ = fetcher_id;
129     run_loop_.Quit();
130   }
OnChunkUpload(int fetcher_id)131   virtual void OnChunkUpload(int fetcher_id) OVERRIDE {}
OnRequestEnd(int fetcher_id)132   virtual void OnRequestEnd(int fetcher_id) OVERRIDE {}
133 
WaitForRequest()134   int WaitForRequest() {
135     run_loop_.Run();
136     return fetcher_id_;
137   }
138 
139  private:
140   net::TestURLFetcherFactory* factory_;
141   int fetcher_id_;
142   base::RunLoop run_loop_;
143 };
144 }  // namespace
145 
ACTION_P(SetCertificateContents,contents)146 ACTION_P(SetCertificateContents, contents) {
147   arg1->add_certificate_chain()->add_element()->set_certificate(contents);
148 }
149 
ACTION_P(SetDosHeaderContents,contents)150 ACTION_P(SetDosHeaderContents, contents) {
151   arg1->mutable_pe_headers()->set_dos_header(contents);
152 }
153 
ACTION_P(TrustSignature,certificate_file)154 ACTION_P(TrustSignature, certificate_file) {
155   arg1->set_trusted(true);
156   // Add a certificate chain.  Note that we add the certificate twice so that
157   // it appears as its own issuer.
158   std::string cert_data;
159   ASSERT_TRUE(base::ReadFileToString(certificate_file, &cert_data));
160   ClientDownloadRequest_CertificateChain* chain =
161       arg1->add_certificate_chain();
162   chain->add_element()->set_certificate(cert_data);
163   chain->add_element()->set_certificate(cert_data);
164 }
165 
166 // We can't call OnSafeBrowsingResult directly because SafeBrowsingCheck does
167 // not have any copy constructor which means it can't be stored in a callback
168 // easily.  Note: check will be deleted automatically when the callback is
169 // deleted.
OnSafeBrowsingResult(SafeBrowsingDatabaseManager::SafeBrowsingCheck * check)170 void OnSafeBrowsingResult(
171     SafeBrowsingDatabaseManager::SafeBrowsingCheck* check) {
172   check->client->OnSafeBrowsingResult(*check);
173 }
174 
ACTION_P(CheckDownloadUrlDone,threat_type)175 ACTION_P(CheckDownloadUrlDone, threat_type) {
176   SafeBrowsingDatabaseManager::SafeBrowsingCheck* check =
177       new SafeBrowsingDatabaseManager::SafeBrowsingCheck(
178           arg0,
179           std::vector<SBFullHash>(),
180           arg1,
181           safe_browsing_util::BINURL,
182           std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL));
183   for (size_t i = 0; i < check->url_results.size(); ++i)
184     check->url_results[i] = threat_type;
185   BrowserThread::PostTask(BrowserThread::IO,
186                           FROM_HERE,
187                           base::Bind(&OnSafeBrowsingResult,
188                                      base::Owned(check)));
189 }
190 
191 class DownloadProtectionServiceTest : public testing::Test {
192  protected:
DownloadProtectionServiceTest()193   DownloadProtectionServiceTest()
194       : test_browser_thread_bundle_(
195             content::TestBrowserThreadBundle::IO_MAINLOOP) {
196   }
SetUp()197   virtual void SetUp() {
198     // Start real threads for the IO and File threads so that the DCHECKs
199     // to test that we're on the correct thread work.
200     sb_service_ = new StrictMock<FakeSafeBrowsingService>();
201     sb_service_->Initialize();
202     binary_feature_extractor_ = new StrictMock<MockBinaryFeatureExtractor>();
203     download_service_ = sb_service_->download_protection_service();
204     download_service_->binary_feature_extractor_ = binary_feature_extractor_;
205     download_service_->SetEnabled(true);
206     base::RunLoop().RunUntilIdle();
207     has_result_ = false;
208 
209     base::FilePath source_path;
210     ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &source_path));
211     testdata_path_ = source_path
212         .AppendASCII("chrome")
213         .AppendASCII("test")
214         .AppendASCII("data")
215         .AppendASCII("safe_browsing")
216         .AppendASCII("download_protection");
217   }
218 
TearDown()219   virtual void TearDown() {
220     sb_service_->ShutDown();
221     // Flush all of the thread message loops to ensure that there are no
222     // tasks currently running.
223     FlushThreadMessageLoops();
224     sb_service_ = NULL;
225   }
226 
RequestContainsResource(const ClientDownloadRequest & request,ClientDownloadRequest::ResourceType type,const std::string & url,const std::string & referrer)227   bool RequestContainsResource(const ClientDownloadRequest& request,
228                                ClientDownloadRequest::ResourceType type,
229                                const std::string& url,
230                                const std::string& referrer) {
231     for (int i = 0; i < request.resources_size(); ++i) {
232       if (request.resources(i).url() == url &&
233           request.resources(i).type() == type &&
234           (referrer.empty() || request.resources(i).referrer() == referrer)) {
235         return true;
236       }
237     }
238     return false;
239   }
240 
241   // At this point we only set the server IP for the download itself.
RequestContainsServerIp(const ClientDownloadRequest & request,const std::string & remote_address)242   bool RequestContainsServerIp(const ClientDownloadRequest& request,
243                                const std::string& remote_address) {
244     for (int i = 0; i < request.resources_size(); ++i) {
245       // We want the last DOWNLOAD_URL in the chain.
246       if (request.resources(i).type() == ClientDownloadRequest::DOWNLOAD_URL &&
247           (i + 1 == request.resources_size() ||
248            request.resources(i + 1).type() !=
249            ClientDownloadRequest::DOWNLOAD_URL)) {
250         return remote_address == request.resources(i).remote_ip();
251       }
252     }
253     return false;
254   }
255 
256   // Flushes any pending tasks in the message loops of all threads.
FlushThreadMessageLoops()257   void FlushThreadMessageLoops() {
258     BrowserThread::GetBlockingPool()->FlushForTesting();
259     FlushMessageLoop(BrowserThread::IO);
260     base::RunLoop().RunUntilIdle();
261   }
262 
263   // Proxy for private method.
GetCertificateWhitelistStrings(const net::X509Certificate & certificate,const net::X509Certificate & issuer,std::vector<std::string> * whitelist_strings)264   static void GetCertificateWhitelistStrings(
265       const net::X509Certificate& certificate,
266       const net::X509Certificate& issuer,
267       std::vector<std::string>* whitelist_strings) {
268     DownloadProtectionService::GetCertificateWhitelistStrings(
269         certificate, issuer, whitelist_strings);
270   }
271 
272   // Reads a single PEM-encoded certificate from the testdata directory.
273   // Returns NULL on failure.
ReadTestCertificate(const std::string & filename)274   scoped_refptr<net::X509Certificate> ReadTestCertificate(
275       const std::string& filename) {
276     std::string cert_data;
277     if (!base::ReadFileToString(testdata_path_.AppendASCII(filename),
278                                 &cert_data)) {
279       return NULL;
280     }
281     net::CertificateList certs =
282         net::X509Certificate::CreateCertificateListFromBytes(
283             cert_data.data(),
284             cert_data.size(),
285             net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
286     return certs.empty() ? NULL : certs[0];
287   }
288 
289  private:
290   // Helper functions for FlushThreadMessageLoops.
RunAllPendingAndQuitUI()291   void RunAllPendingAndQuitUI() {
292     base::MessageLoop::current()->RunUntilIdle();
293     BrowserThread::PostTask(
294         BrowserThread::UI,
295         FROM_HERE,
296         base::Bind(&DownloadProtectionServiceTest::QuitMessageLoop,
297                    base::Unretained(this)));
298   }
299 
QuitMessageLoop()300   void QuitMessageLoop() {
301     base::MessageLoop::current()->Quit();
302   }
303 
PostRunMessageLoopTask(BrowserThread::ID thread)304   void PostRunMessageLoopTask(BrowserThread::ID thread) {
305     BrowserThread::PostTask(
306         thread,
307         FROM_HERE,
308         base::Bind(&DownloadProtectionServiceTest::RunAllPendingAndQuitUI,
309                    base::Unretained(this)));
310   }
311 
FlushMessageLoop(BrowserThread::ID thread)312   void FlushMessageLoop(BrowserThread::ID thread) {
313     BrowserThread::PostTask(
314         BrowserThread::UI,
315         FROM_HERE,
316         base::Bind(&DownloadProtectionServiceTest::PostRunMessageLoopTask,
317                    base::Unretained(this), thread));
318     MessageLoop::current()->Run();
319   }
320 
321  public:
CheckDoneCallback(DownloadProtectionService::DownloadCheckResult result)322   void CheckDoneCallback(
323       DownloadProtectionService::DownloadCheckResult result) {
324     result_ = result;
325     has_result_ = true;
326     MessageLoop::current()->Quit();
327   }
328 
SyncCheckDoneCallback(DownloadProtectionService::DownloadCheckResult result)329   void SyncCheckDoneCallback(
330       DownloadProtectionService::DownloadCheckResult result) {
331     result_ = result;
332     has_result_ = true;
333   }
334 
SendURLFetchComplete(net::TestURLFetcher * fetcher)335   void SendURLFetchComplete(net::TestURLFetcher* fetcher) {
336     fetcher->delegate()->OnURLFetchComplete(fetcher);
337   }
338 
IsResult(DownloadProtectionService::DownloadCheckResult expected)339   testing::AssertionResult IsResult(
340       DownloadProtectionService::DownloadCheckResult expected) {
341     if (!has_result_)
342       return testing::AssertionFailure() << "No result";
343     has_result_ = false;
344     return result_ == expected ?
345         testing::AssertionSuccess() :
346         testing::AssertionFailure() << "Expected " << expected <<
347                                        ", got " << result_;
348   }
349 
350  protected:
351   scoped_refptr<FakeSafeBrowsingService> sb_service_;
352   scoped_refptr<MockBinaryFeatureExtractor> binary_feature_extractor_;
353   DownloadProtectionService* download_service_;
354   DownloadProtectionService::DownloadCheckResult result_;
355   bool has_result_;
356   content::TestBrowserThreadBundle test_browser_thread_bundle_;
357   content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
358   base::FilePath testdata_path_;
359 };
360 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadInvalidUrl)361 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadInvalidUrl) {
362   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
363   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
364   std::vector<GURL> url_chain;
365   GURL referrer("http://www.google.com/");
366 
367   content::MockDownloadItem item;
368   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
369   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
370   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
371   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
372   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
373   EXPECT_CALL(item, GetTabReferrerUrl())
374       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
375   download_service_->CheckClientDownload(
376       &item,
377       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
378                  base::Unretained(this)));
379   MessageLoop::current()->Run();
380   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
381   Mock::VerifyAndClearExpectations(&item);
382 
383   url_chain.push_back(GURL("file://www.google.com/"));
384   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
385   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
386   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
387   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
388   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
389   EXPECT_CALL(item, GetTabReferrerUrl())
390       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
391   download_service_->CheckClientDownload(
392       &item,
393       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
394                  base::Unretained(this)));
395   MessageLoop::current()->Run();
396   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
397 }
398 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadWhitelistedUrl)399 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadWhitelistedUrl) {
400   // Response to any requests will be DANGEROUS.
401   ClientDownloadResponse response;
402   response.set_verdict(ClientDownloadResponse::DANGEROUS);
403   net::FakeURLFetcherFactory factory(NULL);
404   factory.SetFakeResponse(
405       DownloadProtectionService::GetDownloadRequestUrl(),
406       response.SerializeAsString(),
407       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
408 
409   std::string hash = "hash";
410   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
411   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
412   std::vector<GURL> url_chain;
413   GURL referrer;
414 
415   content::MockDownloadItem item;
416   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
417   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
418   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
419   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
420   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
421   EXPECT_CALL(item, GetTabReferrerUrl())
422       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
423   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
424   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
425   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
426   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
427   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
428       .Times(4);
429   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
430       .Times(4);
431 
432   // We should not get whilelist checks for other URLs than specified below.
433   EXPECT_CALL(*sb_service_->mock_database_manager(),
434               MatchDownloadWhitelistUrl(_)).Times(0);
435   EXPECT_CALL(*sb_service_->mock_database_manager(),
436               MatchDownloadWhitelistUrl(GURL("http://www.evil.com/bla.exe")))
437       .WillRepeatedly(Return(false));
438   EXPECT_CALL(*sb_service_->mock_database_manager(),
439               MatchDownloadWhitelistUrl(GURL("http://www.google.com/a.exe")))
440       .WillRepeatedly(Return(true));
441 
442   // With no referrer and just the bad url, should be marked DANGEROUS.
443   url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
444   download_service_->CheckClientDownload(
445       &item,
446       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
447                  base::Unretained(this)));
448   MessageLoop::current()->Run();
449 #if defined(OS_WIN)
450   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
451 #else
452   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
453 #endif
454 
455   // Check that the referrer is not matched against the whitelist.
456   referrer = GURL("http://www.google.com/");
457   download_service_->CheckClientDownload(
458       &item,
459       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
460                  base::Unretained(this)));
461   MessageLoop::current()->Run();
462 #if defined(OS_WIN)
463   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
464 #else
465   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
466 #endif
467 
468   // Redirect from a site shouldn't be checked either.
469   url_chain.insert(url_chain.begin(), GURL("http://www.google.com/redirect"));
470   download_service_->CheckClientDownload(
471       &item,
472       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
473                  base::Unretained(this)));
474   MessageLoop::current()->Run();
475 #if defined(OS_WIN)
476   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
477 #else
478   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
479 #endif
480 
481   // Only if the final url is whitelisted should it be SAFE.
482   url_chain.push_back(GURL("http://www.google.com/a.exe"));
483   download_service_->CheckClientDownload(
484       &item,
485       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
486                  base::Unretained(this)));
487   MessageLoop::current()->Run();
488   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
489 }
490 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadFetchFailed)491 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadFetchFailed) {
492   net::FakeURLFetcherFactory factory(NULL);
493   // HTTP request will fail.
494   factory.SetFakeResponse(
495       DownloadProtectionService::GetDownloadRequestUrl(), std::string(),
496       net::HTTP_INTERNAL_SERVER_ERROR, net::URLRequestStatus::FAILED);
497 
498   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
499   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
500   std::vector<GURL> url_chain;
501   url_chain.push_back(GURL("http://www.evil.com/a.exe"));
502   GURL referrer("http://www.google.com/");
503   std::string hash = "hash";
504 
505   content::MockDownloadItem item;
506   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
507   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
508   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
509   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
510   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
511   EXPECT_CALL(item, GetTabReferrerUrl())
512       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
513   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
514   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
515   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
516   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
517 
518   EXPECT_CALL(*sb_service_->mock_database_manager(),
519               MatchDownloadWhitelistUrl(_))
520       .WillRepeatedly(Return(false));
521   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _));
522   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _));
523 
524   download_service_->CheckClientDownload(
525       &item,
526       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
527                  base::Unretained(this)));
528   MessageLoop::current()->Run();
529   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
530 }
531 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadSuccess)532 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadSuccess) {
533   ClientDownloadResponse response;
534   response.set_verdict(ClientDownloadResponse::SAFE);
535   net::FakeURLFetcherFactory factory(NULL);
536   // Empty response means SAFE.
537   factory.SetFakeResponse(
538       DownloadProtectionService::GetDownloadRequestUrl(),
539       response.SerializeAsString(),
540       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
541 
542   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
543   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
544   std::vector<GURL> url_chain;
545   url_chain.push_back(GURL("http://www.evil.com/a.exe"));
546   GURL referrer("http://www.google.com/");
547   std::string hash = "hash";
548 
549   content::MockDownloadItem item;
550   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
551   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
552   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
553   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
554   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
555   EXPECT_CALL(item, GetTabReferrerUrl())
556       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
557   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
558   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
559   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
560   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
561 
562   EXPECT_CALL(*sb_service_->mock_database_manager(),
563               MatchDownloadWhitelistUrl(_))
564       .WillRepeatedly(Return(false));
565   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
566       .Times(6);
567   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
568       .Times(6);
569 
570   download_service_->CheckClientDownload(
571       &item,
572       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
573                  base::Unretained(this)));
574   MessageLoop::current()->Run();
575   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
576 
577   // Invalid response should be safe too.
578   response.Clear();
579   factory.SetFakeResponse(
580       DownloadProtectionService::GetDownloadRequestUrl(),
581       response.SerializePartialAsString(),
582       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
583 
584   download_service_->CheckClientDownload(
585       &item,
586       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
587                  base::Unretained(this)));
588   MessageLoop::current()->Run();
589   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
590   std::string feedback_ping;
591   std::string feedback_response;
592   EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
593       item, &feedback_ping, &feedback_response));
594 
595   // If the response is dangerous the result should also be marked as dangerous.
596   response.set_verdict(ClientDownloadResponse::DANGEROUS);
597   factory.SetFakeResponse(
598       DownloadProtectionService::GetDownloadRequestUrl(),
599       response.SerializeAsString(),
600       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
601 
602   download_service_->CheckClientDownload(
603       &item,
604       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
605                  base::Unretained(this)));
606   MessageLoop::current()->Run();
607   EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
608       item, &feedback_ping, &feedback_response));
609 #if defined(OS_WIN)
610   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
611 #else
612   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
613 #endif
614 
615   // If the response is uncommon the result should also be marked as uncommon.
616   response.set_verdict(ClientDownloadResponse::UNCOMMON);
617   factory.SetFakeResponse(
618       DownloadProtectionService::GetDownloadRequestUrl(),
619       response.SerializeAsString(),
620       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
621 
622   download_service_->CheckClientDownload(
623       &item,
624       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
625                  base::Unretained(this)));
626   MessageLoop::current()->Run();
627 #if defined(OS_WIN)
628   EXPECT_TRUE(IsResult(DownloadProtectionService::UNCOMMON));
629   EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting(
630       item, &feedback_ping, &feedback_response));
631   ClientDownloadRequest decoded_request;
632   EXPECT_TRUE(decoded_request.ParseFromString(feedback_ping));
633   EXPECT_EQ(url_chain.back().spec(), decoded_request.url());
634   EXPECT_EQ(response.SerializeAsString(), feedback_response);
635 #else
636   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
637 #endif
638 
639   // If the response is dangerous_host the result should also be marked as
640   // dangerous_host.
641   response.set_verdict(ClientDownloadResponse::DANGEROUS_HOST);
642   factory.SetFakeResponse(
643       DownloadProtectionService::GetDownloadRequestUrl(),
644       response.SerializeAsString(),
645       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
646 
647   download_service_->CheckClientDownload(
648       &item,
649       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
650                  base::Unretained(this)));
651   MessageLoop::current()->Run();
652 #if defined(OS_WIN)
653   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS_HOST));
654   EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting(
655       item, &feedback_ping, &feedback_response));
656   EXPECT_EQ(response.SerializeAsString(), feedback_response);
657 #else
658   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
659 #endif
660 
661   // If the response is POTENTIALLY_UNWANTED the result should also be marked as
662   // POTENTIALLY_UNWANTED.
663   response.set_verdict(ClientDownloadResponse::POTENTIALLY_UNWANTED);
664   factory.SetFakeResponse(
665       DownloadProtectionService::GetDownloadRequestUrl(),
666       response.SerializeAsString(),
667       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
668 
669   download_service_->CheckClientDownload(
670       &item,
671       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
672                  base::Unretained(this)));
673   MessageLoop::current()->Run();
674 #if defined(OS_WIN)
675   EXPECT_TRUE(IsResult(DownloadProtectionService::POTENTIALLY_UNWANTED));
676 #else
677   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
678 #endif
679 }
680 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadHTTPS)681 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadHTTPS) {
682   ClientDownloadResponse response;
683   response.set_verdict(ClientDownloadResponse::DANGEROUS);
684   net::FakeURLFetcherFactory factory(NULL);
685   factory.SetFakeResponse(
686       DownloadProtectionService::GetDownloadRequestUrl(),
687       response.SerializeAsString(),
688       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
689 
690   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
691   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
692   std::vector<GURL> url_chain;
693   url_chain.push_back(GURL("http://www.evil.com/a.exe"));
694   GURL referrer("http://www.google.com/");
695   std::string hash = "hash";
696 
697   content::MockDownloadItem item;
698   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
699   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
700   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
701   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
702   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
703   EXPECT_CALL(item, GetTabReferrerUrl())
704       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
705   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
706   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
707   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
708   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
709 
710   EXPECT_CALL(*sb_service_->mock_database_manager(),
711               MatchDownloadWhitelistUrl(_))
712       .WillRepeatedly(Return(false));
713   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
714       .Times(1);
715   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
716       .Times(1);
717 
718   download_service_->CheckClientDownload(
719       &item,
720       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
721                  base::Unretained(this)));
722   MessageLoop::current()->Run();
723 #if defined(OS_WIN)
724   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
725 #else
726   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
727 #endif
728 }
729 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadZip)730 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadZip) {
731   ClientDownloadResponse response;
732   response.set_verdict(ClientDownloadResponse::SAFE);
733   net::FakeURLFetcherFactory factory(NULL);
734   // Empty response means SAFE.
735   factory.SetFakeResponse(
736       DownloadProtectionService::GetDownloadRequestUrl(),
737       response.SerializeAsString(),
738       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
739 
740   base::ScopedTempDir download_dir;
741   ASSERT_TRUE(download_dir.CreateUniqueTempDir());
742 
743   base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp")));
744   base::FilePath a_zip(FILE_PATH_LITERAL("a.zip"));
745   std::vector<GURL> url_chain;
746   url_chain.push_back(GURL("http://www.evil.com/a.zip"));
747   GURL referrer("http://www.google.com/");
748   std::string hash = "hash";
749 
750   content::MockDownloadItem item;
751   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
752   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
753   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
754   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
755   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
756   EXPECT_CALL(item, GetTabReferrerUrl())
757       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
758   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
759   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
760   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
761   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
762 
763   // Write out a zip archive to the temporary file.  In this case, it
764   // only contains a text file.
765   base::ScopedTempDir zip_source_dir;
766   ASSERT_TRUE(zip_source_dir.CreateUniqueTempDir());
767   std::string file_contents = "dummy file";
768   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
769       zip_source_dir.path().Append(FILE_PATH_LITERAL("file.txt")),
770       file_contents.data(), file_contents.size()));
771   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false));
772 
773   download_service_->CheckClientDownload(
774       &item,
775       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
776                  base::Unretained(this)));
777   MessageLoop::current()->Run();
778   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
779   Mock::VerifyAndClearExpectations(sb_service_.get());
780   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
781 
782   // Now check with an executable in the zip file as well.
783   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
784       zip_source_dir.path().Append(FILE_PATH_LITERAL("file.exe")),
785       file_contents.data(), file_contents.size()));
786   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false));
787 
788   EXPECT_CALL(*sb_service_->mock_database_manager(),
789               MatchDownloadWhitelistUrl(_))
790       .WillRepeatedly(Return(false));
791 
792   download_service_->CheckClientDownload(
793       &item,
794       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
795                  base::Unretained(this)));
796   MessageLoop::current()->Run();
797   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
798   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
799 
800   // If the response is dangerous the result should also be marked as
801   // dangerous.
802   response.set_verdict(ClientDownloadResponse::DANGEROUS);
803   factory.SetFakeResponse(
804       DownloadProtectionService::GetDownloadRequestUrl(),
805       response.SerializeAsString(),
806       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
807 
808   download_service_->CheckClientDownload(
809       &item,
810       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
811                  base::Unretained(this)));
812   MessageLoop::current()->Run();
813 #if defined(OS_WIN)
814   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
815 #else
816   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
817 #endif
818   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
819 }
820 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadCorruptZip)821 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadCorruptZip) {
822   base::ScopedTempDir download_dir;
823   ASSERT_TRUE(download_dir.CreateUniqueTempDir());
824 
825   base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp")));
826   base::FilePath a_zip(FILE_PATH_LITERAL("a.zip"));
827   std::vector<GURL> url_chain;
828   url_chain.push_back(GURL("http://www.evil.com/a.zip"));
829   GURL referrer("http://www.google.com/");
830   std::string hash = "hash";
831 
832   content::MockDownloadItem item;
833   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
834   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
835   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
836   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
837   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
838   EXPECT_CALL(item, GetTabReferrerUrl())
839       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
840   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
841   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
842   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
843   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
844 
845   std::string file_contents = "corrupt zip file";
846   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
847       a_tmp, file_contents.data(), file_contents.size()));
848 
849   download_service_->CheckClientDownload(
850       &item,
851       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
852                  base::Unretained(this)));
853   MessageLoop::current()->Run();
854   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
855   Mock::VerifyAndClearExpectations(sb_service_.get());
856   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
857 }
858 
TEST_F(DownloadProtectionServiceTest,CheckClientCrxDownloadSuccess)859 TEST_F(DownloadProtectionServiceTest, CheckClientCrxDownloadSuccess) {
860   ClientDownloadResponse response;
861   // Even if the server verdict is dangerous we should return SAFE because
862   // DownloadProtectionService::IsSupportedDownload() will return false
863   // for crx downloads.
864   response.set_verdict(ClientDownloadResponse::DANGEROUS);
865   net::FakeURLFetcherFactory factory(NULL);
866   // Empty response means SAFE.
867   factory.SetFakeResponse(
868       DownloadProtectionService::GetDownloadRequestUrl(),
869       response.SerializeAsString(),
870       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
871 
872   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
873   base::FilePath a_crx(FILE_PATH_LITERAL("a.crx"));
874   std::vector<GURL> url_chain;
875   url_chain.push_back(GURL("http://www.evil.com/a.crx"));
876   GURL referrer("http://www.google.com/");
877   std::string hash = "hash";
878 
879   content::MockDownloadItem item;
880   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
881   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_crx));
882   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
883   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
884   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
885   EXPECT_CALL(item, GetTabReferrerUrl())
886       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
887   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
888   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
889   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
890   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
891 
892   EXPECT_CALL(*sb_service_->mock_database_manager(),
893               MatchDownloadWhitelistUrl(_))
894       .WillRepeatedly(Return(false));
895   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
896       .Times(1);
897   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
898       .Times(1);
899 
900   EXPECT_FALSE(download_service_->IsSupportedDownload(item, a_crx));
901   download_service_->CheckClientDownload(
902       &item,
903       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
904                  base::Unretained(this)));
905   MessageLoop::current()->Run();
906   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
907 }
908 
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadValidateRequest)909 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadValidateRequest) {
910   net::TestURLFetcherFactory factory;
911 
912   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
913   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
914   std::vector<GURL> url_chain;
915   url_chain.push_back(GURL("http://www.google.com/"));
916   url_chain.push_back(GURL("http://www.google.com/bla.exe"));
917   GURL referrer("http://www.google.com/");
918   std::string hash = "hash";
919   std::string remote_address = "10.11.12.13";
920 
921   content::MockDownloadItem item;
922   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
923   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
924   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
925   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
926   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
927   EXPECT_CALL(item, GetTabReferrerUrl())
928       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
929   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
930   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
931   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
932   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
933 
934   EXPECT_CALL(*sb_service_->mock_database_manager(),
935               MatchDownloadWhitelistUrl(_))
936       .WillRepeatedly(Return(false));
937   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
938       .WillOnce(SetCertificateContents("dummy cert data"));
939   EXPECT_CALL(*binary_feature_extractor_.get(),
940               ExtractImageHeaders(tmp_path, _))
941       .WillOnce(SetDosHeaderContents("dummy dos header"));
942   download_service_->CheckClientDownload(
943       &item,
944       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
945                  base::Unretained(this)));
946 
947 #if !defined(OS_WIN)
948   // SendRequest is not called.  Wait for FinishRequest to call our callback.
949   MessageLoop::current()->Run();
950   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
951   EXPECT_EQ(NULL, fetcher);
952 #else
953   // Run the message loop(s) until SendRequest is called.
954   FlushThreadMessageLoops();
955   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
956   ASSERT_TRUE(fetcher);
957   ClientDownloadRequest request;
958   EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
959   EXPECT_EQ("http://www.google.com/bla.exe", request.url());
960   EXPECT_EQ(hash, request.digests().sha256());
961   EXPECT_EQ(item.GetReceivedBytes(), request.length());
962   EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
963   EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
964   EXPECT_EQ(2, request.resources_size());
965   EXPECT_TRUE(RequestContainsResource(request,
966                                       ClientDownloadRequest::DOWNLOAD_REDIRECT,
967                                       "http://www.google.com/", ""));
968   EXPECT_TRUE(RequestContainsResource(request,
969                                       ClientDownloadRequest::DOWNLOAD_URL,
970                                       "http://www.google.com/bla.exe",
971                                       referrer.spec()));
972   EXPECT_TRUE(request.has_signature());
973   ASSERT_EQ(1, request.signature().certificate_chain_size());
974   const ClientDownloadRequest_CertificateChain& chain =
975       request.signature().certificate_chain(0);
976   ASSERT_EQ(1, chain.element_size());
977   EXPECT_EQ("dummy cert data", chain.element(0).certificate());
978   EXPECT_TRUE(request.has_image_headers());
979   const ClientDownloadRequest_ImageHeaders& headers =
980       request.image_headers();
981   EXPECT_TRUE(headers.has_pe_headers());
982   EXPECT_TRUE(headers.pe_headers().has_dos_header());
983   EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
984 
985   // Simulate the request finishing.
986   base::MessageLoop::current()->PostTask(
987       FROM_HERE,
988       base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
989                  base::Unretained(this), fetcher));
990   MessageLoop::current()->Run();
991 #endif
992 }
993 
994 // Similar to above, but with an unsigned binary.
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadValidateRequestNoSignature)995 TEST_F(DownloadProtectionServiceTest,
996        CheckClientDownloadValidateRequestNoSignature) {
997   net::TestURLFetcherFactory factory;
998 
999   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1000   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1001   std::vector<GURL> url_chain;
1002   url_chain.push_back(GURL("http://www.google.com/"));
1003   url_chain.push_back(GURL("ftp://www.google.com/bla.exe"));
1004   GURL referrer("http://www.google.com/");
1005   std::string hash = "hash";
1006   std::string remote_address = "10.11.12.13";
1007 
1008   content::MockDownloadItem item;
1009   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1010   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1011   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1012   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1013   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1014   EXPECT_CALL(item, GetTabReferrerUrl())
1015       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1016   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1017   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1018   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1019   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1020 
1021   EXPECT_CALL(*sb_service_->mock_database_manager(),
1022               MatchDownloadWhitelistUrl(_))
1023       .WillRepeatedly(Return(false));
1024   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1025   EXPECT_CALL(*binary_feature_extractor_.get(),
1026               ExtractImageHeaders(tmp_path, _));
1027   download_service_->CheckClientDownload(
1028       &item,
1029       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1030                  base::Unretained(this)));
1031 
1032 #if !defined(OS_WIN)
1033   // SendRequest is not called.  Wait for FinishRequest to call our callback.
1034   MessageLoop::current()->Run();
1035   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1036   EXPECT_EQ(NULL, fetcher);
1037 #else
1038   // Run the message loop(s) until SendRequest is called.
1039   FlushThreadMessageLoops();
1040   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1041   ASSERT_TRUE(fetcher);
1042   ClientDownloadRequest request;
1043   EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1044   EXPECT_EQ("ftp://www.google.com/bla.exe", request.url());
1045   EXPECT_EQ(hash, request.digests().sha256());
1046   EXPECT_EQ(item.GetReceivedBytes(), request.length());
1047   EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1048   EXPECT_EQ(2, request.resources_size());
1049   EXPECT_TRUE(RequestContainsResource(request,
1050                                       ClientDownloadRequest::DOWNLOAD_REDIRECT,
1051                                       "http://www.google.com/", ""));
1052   EXPECT_TRUE(RequestContainsResource(request,
1053                                       ClientDownloadRequest::DOWNLOAD_URL,
1054                                       "ftp://www.google.com/bla.exe",
1055                                       referrer.spec()));
1056   EXPECT_TRUE(request.has_signature());
1057   EXPECT_EQ(0, request.signature().certificate_chain_size());
1058 
1059   // Simulate the request finishing.
1060   base::MessageLoop::current()->PostTask(
1061       FROM_HERE,
1062       base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1063                  base::Unretained(this), fetcher));
1064   MessageLoop::current()->Run();
1065 #endif
1066 }
1067 
1068 // Similar to above, but with tab history.
TEST_F(DownloadProtectionServiceTest,CheckClientDownloadValidateRequestTabHistory)1069 TEST_F(DownloadProtectionServiceTest,
1070        CheckClientDownloadValidateRequestTabHistory) {
1071   net::TestURLFetcherFactory factory;
1072 
1073   base::ScopedTempDir profile_dir;
1074   ASSERT_TRUE(profile_dir.CreateUniqueTempDir());
1075   TestingProfile profile(profile_dir.path());
1076   ASSERT_TRUE(
1077       profile.CreateHistoryService(true /* delete_file */, false /* no_db */));
1078 
1079   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1080   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1081   std::vector<GURL> url_chain;
1082   url_chain.push_back(GURL("http://www.google.com/"));
1083   url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1084   GURL referrer("http://www.google.com/");
1085   GURL tab_url("http://tab.com/final");
1086   GURL tab_referrer("http://tab.com/referrer");
1087   std::string hash = "hash";
1088   std::string remote_address = "10.11.12.13";
1089 
1090   content::MockDownloadItem item;
1091   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1092   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1093   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1094   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1095   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
1096   EXPECT_CALL(item, GetTabReferrerUrl())
1097       .WillRepeatedly(ReturnRef(tab_referrer));
1098   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1099   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1100   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1101   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1102   EXPECT_CALL(item, GetBrowserContext()).WillRepeatedly(Return(&profile));
1103   EXPECT_CALL(*sb_service_->mock_database_manager(),
1104               MatchDownloadWhitelistUrl(_))
1105       .WillRepeatedly(Return(false));
1106   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
1107       .WillRepeatedly(SetCertificateContents("dummy cert data"));
1108   EXPECT_CALL(*binary_feature_extractor_.get(),
1109               ExtractImageHeaders(tmp_path, _))
1110       .WillRepeatedly(SetDosHeaderContents("dummy dos header"));
1111 
1112   // First test with no history match for the tab URL.
1113   {
1114     TestURLFetcherWatcher fetcher_watcher(&factory);
1115     download_service_->CheckClientDownload(
1116         &item,
1117         base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1118                    base::Unretained(this)));
1119 
1120 #if !defined(OS_WIN)
1121     // SendRequest is not called.  Wait for FinishRequest to call our callback.
1122     MessageLoop::current()->Run();
1123     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1124     EXPECT_EQ(NULL, fetcher);
1125 #else
1126     EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
1127     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1128     ASSERT_TRUE(fetcher);
1129     ClientDownloadRequest request;
1130     EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1131     EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1132     EXPECT_EQ(hash, request.digests().sha256());
1133     EXPECT_EQ(item.GetReceivedBytes(), request.length());
1134     EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1135     EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1136     EXPECT_EQ(3, request.resources_size());
1137     EXPECT_TRUE(
1138         RequestContainsResource(request,
1139                                 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1140                                 "http://www.google.com/",
1141                                 ""));
1142     EXPECT_TRUE(RequestContainsResource(request,
1143                                         ClientDownloadRequest::DOWNLOAD_URL,
1144                                         "http://www.google.com/bla.exe",
1145                                         referrer.spec()));
1146     EXPECT_TRUE(RequestContainsResource(request,
1147                                         ClientDownloadRequest::TAB_URL,
1148                                         tab_url.spec(),
1149                                         tab_referrer.spec()));
1150     EXPECT_TRUE(request.has_signature());
1151     ASSERT_EQ(1, request.signature().certificate_chain_size());
1152     const ClientDownloadRequest_CertificateChain& chain =
1153         request.signature().certificate_chain(0);
1154     ASSERT_EQ(1, chain.element_size());
1155     EXPECT_EQ("dummy cert data", chain.element(0).certificate());
1156     EXPECT_TRUE(request.has_image_headers());
1157     const ClientDownloadRequest_ImageHeaders& headers =
1158         request.image_headers();
1159     EXPECT_TRUE(headers.has_pe_headers());
1160     EXPECT_TRUE(headers.pe_headers().has_dos_header());
1161     EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
1162 
1163     // Simulate the request finishing.
1164     base::MessageLoop::current()->PostTask(
1165         FROM_HERE,
1166         base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1167                    base::Unretained(this),
1168                    fetcher));
1169     MessageLoop::current()->Run();
1170 #endif
1171   }
1172 
1173   // Now try with a history match.
1174   {
1175     history::RedirectList redirects;
1176     redirects.push_back(GURL("http://tab.com/ref1"));
1177     redirects.push_back(GURL("http://tab.com/ref2"));
1178     redirects.push_back(tab_url);
1179     HistoryServiceFactory::GetForProfile(&profile, Profile::EXPLICIT_ACCESS)
1180         ->AddPage(tab_url,
1181                   base::Time::Now(),
1182                   static_cast<void*>(this),
1183                   0,
1184                   GURL(),
1185                   redirects,
1186                   content::PAGE_TRANSITION_TYPED,
1187                   history::SOURCE_BROWSED,
1188                   false);
1189 
1190     TestURLFetcherWatcher fetcher_watcher(&factory);
1191     download_service_->CheckClientDownload(
1192         &item,
1193         base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1194                    base::Unretained(this)));
1195 #if !defined(OS_WIN)
1196     // SendRequest is not called.  Wait for FinishRequest to call our callback.
1197     MessageLoop::current()->Run();
1198     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1199     EXPECT_EQ(NULL, fetcher);
1200 #else
1201     EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
1202     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1203     ASSERT_TRUE(fetcher);
1204     ClientDownloadRequest request;
1205     EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1206     EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1207     EXPECT_EQ(hash, request.digests().sha256());
1208     EXPECT_EQ(item.GetReceivedBytes(), request.length());
1209     EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1210     EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1211     EXPECT_EQ(5, request.resources_size());
1212     EXPECT_TRUE(
1213         RequestContainsResource(request,
1214                                 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1215                                 "http://www.google.com/",
1216                                 ""));
1217     EXPECT_TRUE(RequestContainsResource(request,
1218                                         ClientDownloadRequest::DOWNLOAD_URL,
1219                                         "http://www.google.com/bla.exe",
1220                                         referrer.spec()));
1221     EXPECT_TRUE(RequestContainsResource(request,
1222                                         ClientDownloadRequest::TAB_REDIRECT,
1223                                         "http://tab.com/ref1",
1224                                         ""));
1225     EXPECT_TRUE(RequestContainsResource(request,
1226                                         ClientDownloadRequest::TAB_REDIRECT,
1227                                         "http://tab.com/ref2",
1228                                         ""));
1229     EXPECT_TRUE(RequestContainsResource(request,
1230                                         ClientDownloadRequest::TAB_URL,
1231                                         tab_url.spec(),
1232                                         tab_referrer.spec()));
1233     EXPECT_TRUE(request.has_signature());
1234     ASSERT_EQ(1, request.signature().certificate_chain_size());
1235     const ClientDownloadRequest_CertificateChain& chain =
1236         request.signature().certificate_chain(0);
1237     ASSERT_EQ(1, chain.element_size());
1238     EXPECT_EQ("dummy cert data", chain.element(0).certificate());
1239 
1240     // Simulate the request finishing.
1241     base::MessageLoop::current()->PostTask(
1242         FROM_HERE,
1243         base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1244                    base::Unretained(this),
1245                    fetcher));
1246     MessageLoop::current()->Run();
1247 #endif
1248   }
1249 }
1250 
TEST_F(DownloadProtectionServiceTest,TestCheckDownloadUrl)1251 TEST_F(DownloadProtectionServiceTest, TestCheckDownloadUrl) {
1252   std::vector<GURL> url_chain;
1253   url_chain.push_back(GURL("http://www.google.com/"));
1254   url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1255   GURL referrer("http://www.google.com/");
1256   std::string hash = "hash";
1257 
1258   content::MockDownloadItem item;
1259   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1260   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1261   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1262 
1263   // CheckDownloadURL returns immediately which means the client object callback
1264   // will never be called.  Nevertheless the callback provided to
1265   // CheckClientDownload must still be called.
1266   EXPECT_CALL(*sb_service_->mock_database_manager(),
1267               CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1268       .WillOnce(Return(true));
1269   download_service_->CheckDownloadUrl(
1270       item,
1271       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1272                  base::Unretained(this)));
1273   MessageLoop::current()->Run();
1274   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1275   Mock::VerifyAndClearExpectations(sb_service_.get());
1276 
1277   EXPECT_CALL(*sb_service_->mock_database_manager(),
1278               CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1279       .WillOnce(DoAll(CheckDownloadUrlDone(SB_THREAT_TYPE_SAFE),
1280                       Return(false)));
1281   download_service_->CheckDownloadUrl(
1282       item,
1283       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1284                  base::Unretained(this)));
1285   MessageLoop::current()->Run();
1286   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1287   Mock::VerifyAndClearExpectations(sb_service_.get());
1288 
1289   EXPECT_CALL(*sb_service_->mock_database_manager(),
1290               CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1291       .WillOnce(DoAll(
1292           CheckDownloadUrlDone(SB_THREAT_TYPE_URL_MALWARE),
1293           Return(false)));
1294   download_service_->CheckDownloadUrl(
1295       item,
1296       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1297                  base::Unretained(this)));
1298   MessageLoop::current()->Run();
1299   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1300   Mock::VerifyAndClearExpectations(sb_service_.get());
1301 
1302   EXPECT_CALL(*sb_service_->mock_database_manager(),
1303               CheckDownloadUrl(ContainerEq(url_chain),
1304                                NotNull()))
1305       .WillOnce(DoAll(
1306           CheckDownloadUrlDone(SB_THREAT_TYPE_BINARY_MALWARE_URL),
1307           Return(false)));
1308   download_service_->CheckDownloadUrl(
1309       item,
1310       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1311                  base::Unretained(this)));
1312   MessageLoop::current()->Run();
1313   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
1314 }
1315 
TEST_F(DownloadProtectionServiceTest,TestDownloadRequestTimeout)1316 TEST_F(DownloadProtectionServiceTest, TestDownloadRequestTimeout) {
1317   net::TestURLFetcherFactory factory;
1318 
1319   std::vector<GURL> url_chain;
1320   url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1321   GURL referrer("http://www.google.com/");
1322   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1323   base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1324   std::string hash = "hash";
1325 
1326   content::MockDownloadItem item;
1327   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1328   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1329   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1330   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1331   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1332   EXPECT_CALL(item, GetTabReferrerUrl())
1333       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1334   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1335   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1336   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1337   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1338 
1339   EXPECT_CALL(*sb_service_->mock_database_manager(),
1340               MatchDownloadWhitelistUrl(_))
1341       .WillRepeatedly(Return(false));
1342   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1343   EXPECT_CALL(*binary_feature_extractor_.get(),
1344               ExtractImageHeaders(tmp_path, _));
1345 
1346   download_service_->download_request_timeout_ms_ = 10;
1347   download_service_->CheckClientDownload(
1348       &item,
1349       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1350                  base::Unretained(this)));
1351 
1352   // The request should time out because the HTTP request hasn't returned
1353   // anything yet.
1354   MessageLoop::current()->Run();
1355   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1356 }
1357 
TEST_F(DownloadProtectionServiceTest,TestDownloadItemDestroyed)1358 TEST_F(DownloadProtectionServiceTest, TestDownloadItemDestroyed) {
1359   net::TestURLFetcherFactory factory;
1360 
1361   std::vector<GURL> url_chain;
1362   url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1363   GURL referrer("http://www.google.com/");
1364   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1365   base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1366   std::string hash = "hash";
1367 
1368   {
1369     content::MockDownloadItem item;
1370     EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1371     EXPECT_CALL(item, GetTargetFilePath())
1372         .WillRepeatedly(ReturnRef(final_path));
1373     EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1374     EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1375     EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1376     EXPECT_CALL(item, GetTabReferrerUrl())
1377         .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1378     EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1379     EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1380     EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1381     EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1382 
1383     EXPECT_CALL(*sb_service_->mock_database_manager(),
1384                 MatchDownloadWhitelistUrl(_))
1385         .WillRepeatedly(Return(false));
1386     EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1387     EXPECT_CALL(*binary_feature_extractor_.get(),
1388                 ExtractImageHeaders(tmp_path, _));
1389 
1390     download_service_->CheckClientDownload(
1391         &item,
1392         base::Bind(&DownloadProtectionServiceTest::SyncCheckDoneCallback,
1393                    base::Unretained(this)));
1394     // MockDownloadItem going out of scope triggers the OnDownloadDestroyed
1395     // notification.
1396   }
1397 
1398   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1399 }
1400 
TEST_F(DownloadProtectionServiceTest,GetCertificateWhitelistStrings)1401 TEST_F(DownloadProtectionServiceTest, GetCertificateWhitelistStrings) {
1402   // We'll pass this cert in as the "issuer", even though it isn't really
1403   // used to sign the certs below.  GetCertificateWhitelistStirngs doesn't care
1404   // about this.
1405   scoped_refptr<net::X509Certificate> issuer_cert(
1406       ReadTestCertificate("issuer.pem"));
1407   ASSERT_TRUE(issuer_cert.get());
1408   std::string cert_base = "cert/" + base::HexEncode(
1409       issuer_cert->fingerprint().data,
1410       sizeof(issuer_cert->fingerprint().data));
1411 
1412   scoped_refptr<net::X509Certificate> cert(ReadTestCertificate("test_cn.pem"));
1413   ASSERT_TRUE(cert.get());
1414   std::vector<std::string> whitelist_strings;
1415   GetCertificateWhitelistStrings(
1416       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1417   // This also tests escaping of characters in the certificate attributes.
1418   EXPECT_THAT(whitelist_strings, ElementsAre(
1419       cert_base + "/CN=subject%2F%251"));
1420 
1421   cert = ReadTestCertificate("test_cn_o.pem");
1422   ASSERT_TRUE(cert.get());
1423   whitelist_strings.clear();
1424   GetCertificateWhitelistStrings(
1425       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1426   EXPECT_THAT(whitelist_strings,
1427               ElementsAre(cert_base + "/CN=subject",
1428                           cert_base + "/CN=subject/O=org",
1429                           cert_base + "/O=org"));
1430 
1431   cert = ReadTestCertificate("test_cn_o_ou.pem");
1432   ASSERT_TRUE(cert.get());
1433   whitelist_strings.clear();
1434   GetCertificateWhitelistStrings(
1435       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1436   EXPECT_THAT(whitelist_strings,
1437               ElementsAre(cert_base + "/CN=subject",
1438                           cert_base + "/CN=subject/O=org",
1439                           cert_base + "/CN=subject/O=org/OU=unit",
1440                           cert_base + "/CN=subject/OU=unit",
1441                           cert_base + "/O=org",
1442                           cert_base + "/O=org/OU=unit",
1443                           cert_base + "/OU=unit"));
1444 
1445   cert = ReadTestCertificate("test_cn_ou.pem");
1446   ASSERT_TRUE(cert.get());
1447   whitelist_strings.clear();
1448   GetCertificateWhitelistStrings(
1449       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1450   EXPECT_THAT(whitelist_strings,
1451               ElementsAre(cert_base + "/CN=subject",
1452                           cert_base + "/CN=subject/OU=unit",
1453                           cert_base + "/OU=unit"));
1454 
1455   cert = ReadTestCertificate("test_o.pem");
1456   ASSERT_TRUE(cert.get());
1457   whitelist_strings.clear();
1458   GetCertificateWhitelistStrings(
1459       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1460   EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/O=org"));
1461 
1462   cert = ReadTestCertificate("test_o_ou.pem");
1463   ASSERT_TRUE(cert.get());
1464   whitelist_strings.clear();
1465   GetCertificateWhitelistStrings(
1466       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1467   EXPECT_THAT(whitelist_strings,
1468               ElementsAre(cert_base + "/O=org",
1469                           cert_base + "/O=org/OU=unit",
1470                           cert_base + "/OU=unit"));
1471 
1472   cert = ReadTestCertificate("test_ou.pem");
1473   ASSERT_TRUE(cert.get());
1474   whitelist_strings.clear();
1475   GetCertificateWhitelistStrings(
1476       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1477   EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/OU=unit"));
1478 
1479   cert = ReadTestCertificate("test_c.pem");
1480   ASSERT_TRUE(cert.get());
1481   whitelist_strings.clear();
1482   GetCertificateWhitelistStrings(
1483       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1484   EXPECT_THAT(whitelist_strings, ElementsAre());
1485 }
1486 }  // namespace safe_browsing
1487