Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / download_protection_service_unittest.cc
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/files/file_path.h"
14 #include "base/files/file_util.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 #if defined(OS_MACOSX)
45 #include "base/metrics/field_trial.h"
46 #include "components/variations/entropy_provider.h"
47 #endif
48
49 using ::testing::Assign;
50 using ::testing::ContainerEq;
51 using ::testing::DoAll;
52 using ::testing::ElementsAre;
53 using ::testing::Invoke;
54 using ::testing::Mock;
55 using ::testing::NotNull;
56 using ::testing::Return;
57 using ::testing::ReturnRef;
58 using ::testing::SaveArg;
59 using ::testing::StrictMock;
60 using ::testing::_;
61 using base::MessageLoop;
62 using content::BrowserThread;
63 namespace safe_browsing {
64 namespace {
65 // A SafeBrowsingDatabaseManager implementation that returns a fixed result for
66 // a given URL.
67 class MockSafeBrowsingDatabaseManager : public SafeBrowsingDatabaseManager {
68  public:
69   explicit MockSafeBrowsingDatabaseManager(SafeBrowsingService* service)
70       : SafeBrowsingDatabaseManager(service) { }
71
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));
77
78  private:
79   virtual ~MockSafeBrowsingDatabaseManager() {}
80   DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager);
81 };
82
83 class FakeSafeBrowsingService : public SafeBrowsingService {
84  public:
85   FakeSafeBrowsingService() { }
86
87   // Returned pointer has the same lifespan as the database_manager_ refcounted
88   // object.
89   MockSafeBrowsingDatabaseManager* mock_database_manager() {
90     return mock_database_manager_;
91   }
92
93  protected:
94   ~FakeSafeBrowsingService() override {}
95
96   SafeBrowsingDatabaseManager* CreateDatabaseManager() override {
97     mock_database_manager_ = new MockSafeBrowsingDatabaseManager(this);
98     return mock_database_manager_;
99   }
100
101   void RegisterAllDelayedAnalysis() override {}
102
103  private:
104   MockSafeBrowsingDatabaseManager* mock_database_manager_;
105
106   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
107 };
108
109 class MockBinaryFeatureExtractor : public BinaryFeatureExtractor {
110  public:
111   MockBinaryFeatureExtractor() {}
112   MOCK_METHOD2(CheckSignature, void(const base::FilePath&,
113                                     ClientDownloadRequest_SignatureInfo*));
114   MOCK_METHOD2(ExtractImageHeaders, void(const base::FilePath&,
115                                          ClientDownloadRequest_ImageHeaders*));
116
117  protected:
118   virtual ~MockBinaryFeatureExtractor() {}
119
120  private:
121   DISALLOW_COPY_AND_ASSIGN(MockBinaryFeatureExtractor);
122 };
123
124 class TestURLFetcherWatcher : public net::TestURLFetcherDelegateForTests {
125  public:
126   explicit TestURLFetcherWatcher(net::TestURLFetcherFactory* factory)
127       : factory_(factory), fetcher_id_(-1) {
128     factory_->SetDelegateForTests(this);
129   }
130   ~TestURLFetcherWatcher() {
131     factory_->SetDelegateForTests(NULL);
132   }
133
134   // TestURLFetcherDelegateForTests impl:
135   void OnRequestStart(int fetcher_id) override {
136     fetcher_id_ = fetcher_id;
137     run_loop_.Quit();
138   }
139   void OnChunkUpload(int fetcher_id) override {}
140   void OnRequestEnd(int fetcher_id) override {}
141
142   int WaitForRequest() {
143     run_loop_.Run();
144     return fetcher_id_;
145   }
146
147  private:
148   net::TestURLFetcherFactory* factory_;
149   int fetcher_id_;
150   base::RunLoop run_loop_;
151 };
152 }  // namespace
153
154 ACTION_P(SetCertificateContents, contents) {
155   arg1->add_certificate_chain()->add_element()->set_certificate(contents);
156 }
157
158 ACTION_P(SetDosHeaderContents, contents) {
159   arg1->mutable_pe_headers()->set_dos_header(contents);
160 }
161
162 ACTION_P(TrustSignature, certificate_file) {
163   arg1->set_trusted(true);
164   // Add a certificate chain.  Note that we add the certificate twice so that
165   // it appears as its own issuer.
166   std::string cert_data;
167   ASSERT_TRUE(base::ReadFileToString(certificate_file, &cert_data));
168   ClientDownloadRequest_CertificateChain* chain =
169       arg1->add_certificate_chain();
170   chain->add_element()->set_certificate(cert_data);
171   chain->add_element()->set_certificate(cert_data);
172 }
173
174 // We can't call OnSafeBrowsingResult directly because SafeBrowsingCheck does
175 // not have any copy constructor which means it can't be stored in a callback
176 // easily.  Note: check will be deleted automatically when the callback is
177 // deleted.
178 void OnSafeBrowsingResult(
179     SafeBrowsingDatabaseManager::SafeBrowsingCheck* check) {
180   check->client->OnSafeBrowsingResult(*check);
181 }
182
183 ACTION_P(CheckDownloadUrlDone, threat_type) {
184   SafeBrowsingDatabaseManager::SafeBrowsingCheck* check =
185       new SafeBrowsingDatabaseManager::SafeBrowsingCheck(
186           arg0,
187           std::vector<SBFullHash>(),
188           arg1,
189           safe_browsing_util::BINURL,
190           std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL));
191   for (size_t i = 0; i < check->url_results.size(); ++i)
192     check->url_results[i] = threat_type;
193   BrowserThread::PostTask(BrowserThread::IO,
194                           FROM_HERE,
195                           base::Bind(&OnSafeBrowsingResult,
196                                      base::Owned(check)));
197 }
198
199 class DownloadProtectionServiceTest : public testing::Test {
200  protected:
201   DownloadProtectionServiceTest()
202       : test_browser_thread_bundle_(
203             content::TestBrowserThreadBundle::IO_MAINLOOP) {
204   }
205   void SetUp() override {
206 #if defined(OS_MACOSX)
207     field_trial_list_.reset(new base::FieldTrialList(
208           new metrics::SHA1EntropyProvider("42")));
209     ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
210           "SafeBrowsingOSXClientDownloadPings",
211           "Enabled"));
212 #endif
213     // Start real threads for the IO and File threads so that the DCHECKs
214     // to test that we're on the correct thread work.
215     sb_service_ = new StrictMock<FakeSafeBrowsingService>();
216     sb_service_->Initialize();
217     binary_feature_extractor_ = new StrictMock<MockBinaryFeatureExtractor>();
218     download_service_ = sb_service_->download_protection_service();
219     download_service_->binary_feature_extractor_ = binary_feature_extractor_;
220     download_service_->SetEnabled(true);
221     client_download_request_subscription_ =
222         download_service_->RegisterClientDownloadRequestCallback(
223             base::Bind(&DownloadProtectionServiceTest::OnClientDownloadRequest,
224                        base::Unretained(this)));
225     base::RunLoop().RunUntilIdle();
226     has_result_ = false;
227
228     base::FilePath source_path;
229     ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &source_path));
230     testdata_path_ = source_path
231         .AppendASCII("chrome")
232         .AppendASCII("test")
233         .AppendASCII("data")
234         .AppendASCII("safe_browsing")
235         .AppendASCII("download_protection");
236   }
237
238   void TearDown() override {
239     client_download_request_subscription_.reset();
240     sb_service_->ShutDown();
241     // Flush all of the thread message loops to ensure that there are no
242     // tasks currently running.
243     FlushThreadMessageLoops();
244     sb_service_ = NULL;
245   }
246
247   bool RequestContainsResource(const ClientDownloadRequest& request,
248                                ClientDownloadRequest::ResourceType type,
249                                const std::string& url,
250                                const std::string& referrer) {
251     for (int i = 0; i < request.resources_size(); ++i) {
252       if (request.resources(i).url() == url &&
253           request.resources(i).type() == type &&
254           (referrer.empty() || request.resources(i).referrer() == referrer)) {
255         return true;
256       }
257     }
258     return false;
259   }
260
261   // At this point we only set the server IP for the download itself.
262   bool RequestContainsServerIp(const ClientDownloadRequest& request,
263                                const std::string& remote_address) {
264     for (int i = 0; i < request.resources_size(); ++i) {
265       // We want the last DOWNLOAD_URL in the chain.
266       if (request.resources(i).type() == ClientDownloadRequest::DOWNLOAD_URL &&
267           (i + 1 == request.resources_size() ||
268            request.resources(i + 1).type() !=
269            ClientDownloadRequest::DOWNLOAD_URL)) {
270         return remote_address == request.resources(i).remote_ip();
271       }
272     }
273     return false;
274   }
275
276   // Flushes any pending tasks in the message loops of all threads.
277   void FlushThreadMessageLoops() {
278     BrowserThread::GetBlockingPool()->FlushForTesting();
279     FlushMessageLoop(BrowserThread::IO);
280     base::RunLoop().RunUntilIdle();
281   }
282
283   // Proxy for private method.
284   static void GetCertificateWhitelistStrings(
285       const net::X509Certificate& certificate,
286       const net::X509Certificate& issuer,
287       std::vector<std::string>* whitelist_strings) {
288     DownloadProtectionService::GetCertificateWhitelistStrings(
289         certificate, issuer, whitelist_strings);
290   }
291
292   // Reads a single PEM-encoded certificate from the testdata directory.
293   // Returns NULL on failure.
294   scoped_refptr<net::X509Certificate> ReadTestCertificate(
295       const std::string& filename) {
296     std::string cert_data;
297     if (!base::ReadFileToString(testdata_path_.AppendASCII(filename),
298                                 &cert_data)) {
299       return NULL;
300     }
301     net::CertificateList certs =
302         net::X509Certificate::CreateCertificateListFromBytes(
303             cert_data.data(),
304             cert_data.size(),
305             net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
306     return certs.empty() ? NULL : certs[0];
307   }
308
309   bool HasClientDownloadRequest() const {
310     return last_client_download_request_.get() != NULL;
311   }
312
313   void ClearClientDownloadRequest() { last_client_download_request_.reset(); }
314
315  private:
316   // Helper functions for FlushThreadMessageLoops.
317   void RunAllPendingAndQuitUI() {
318     base::MessageLoop::current()->RunUntilIdle();
319     BrowserThread::PostTask(
320         BrowserThread::UI,
321         FROM_HERE,
322         base::Bind(&DownloadProtectionServiceTest::QuitMessageLoop,
323                    base::Unretained(this)));
324   }
325
326   void QuitMessageLoop() {
327     base::MessageLoop::current()->Quit();
328   }
329
330   void PostRunMessageLoopTask(BrowserThread::ID thread) {
331     BrowserThread::PostTask(
332         thread,
333         FROM_HERE,
334         base::Bind(&DownloadProtectionServiceTest::RunAllPendingAndQuitUI,
335                    base::Unretained(this)));
336   }
337
338   void FlushMessageLoop(BrowserThread::ID thread) {
339     BrowserThread::PostTask(
340         BrowserThread::UI,
341         FROM_HERE,
342         base::Bind(&DownloadProtectionServiceTest::PostRunMessageLoopTask,
343                    base::Unretained(this), thread));
344     MessageLoop::current()->Run();
345   }
346
347   void OnClientDownloadRequest(content::DownloadItem* download,
348                                const ClientDownloadRequest* request) {
349     if (request)
350       last_client_download_request_.reset(new ClientDownloadRequest(*request));
351     else
352       last_client_download_request_.reset();
353   }
354
355  public:
356   void CheckDoneCallback(
357       DownloadProtectionService::DownloadCheckResult result) {
358     result_ = result;
359     has_result_ = true;
360     MessageLoop::current()->Quit();
361   }
362
363   void SyncCheckDoneCallback(
364       DownloadProtectionService::DownloadCheckResult result) {
365     result_ = result;
366     has_result_ = true;
367   }
368
369   void SendURLFetchComplete(net::TestURLFetcher* fetcher) {
370     fetcher->delegate()->OnURLFetchComplete(fetcher);
371   }
372
373   testing::AssertionResult IsResult(
374       DownloadProtectionService::DownloadCheckResult expected) {
375     if (!has_result_)
376       return testing::AssertionFailure() << "No result";
377     has_result_ = false;
378     return result_ == expected ?
379         testing::AssertionSuccess() :
380         testing::AssertionFailure() << "Expected " << expected <<
381                                        ", got " << result_;
382   }
383
384  protected:
385   scoped_refptr<FakeSafeBrowsingService> sb_service_;
386   scoped_refptr<MockBinaryFeatureExtractor> binary_feature_extractor_;
387   DownloadProtectionService* download_service_;
388   DownloadProtectionService::DownloadCheckResult result_;
389   bool has_result_;
390   content::TestBrowserThreadBundle test_browser_thread_bundle_;
391   content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
392   base::FilePath testdata_path_;
393 #if defined(OS_MACOSX)
394   scoped_ptr<base::FieldTrialList> field_trial_list_;
395 #endif
396   DownloadProtectionService::ClientDownloadRequestSubscription
397       client_download_request_subscription_;
398   scoped_ptr<ClientDownloadRequest> last_client_download_request_;
399 };
400
401 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadInvalidUrl) {
402   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
403   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
404   std::vector<GURL> url_chain;
405   GURL referrer("http://www.google.com/");
406
407   content::MockDownloadItem item;
408   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
409   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
410   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
411   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
412   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
413   EXPECT_CALL(item, GetTabReferrerUrl())
414       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
415   download_service_->CheckClientDownload(
416       &item,
417       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
418                  base::Unretained(this)));
419   MessageLoop::current()->Run();
420   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
421   EXPECT_FALSE(HasClientDownloadRequest());
422   Mock::VerifyAndClearExpectations(&item);
423
424   url_chain.push_back(GURL("file://www.google.com/"));
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 }
440
441 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadNotABinary) {
442   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
443   base::FilePath a_txt(FILE_PATH_LITERAL("a.txt"));
444   std::vector<GURL> url_chain;
445   GURL referrer("http://www.google.com/");
446
447   content::MockDownloadItem item;
448   url_chain.push_back(GURL("http://www.example.com/foo"));
449   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
450   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_txt));
451   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
452   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
453   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
454   EXPECT_CALL(item, GetTabReferrerUrl())
455       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
456   download_service_->CheckClientDownload(
457       &item,
458       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
459                  base::Unretained(this)));
460   MessageLoop::current()->Run();
461   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
462   EXPECT_FALSE(HasClientDownloadRequest());
463 }
464
465 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadWhitelistedUrl) {
466   // Response to any requests will be DANGEROUS.
467   ClientDownloadResponse response;
468   response.set_verdict(ClientDownloadResponse::DANGEROUS);
469   net::FakeURLFetcherFactory factory(NULL);
470   factory.SetFakeResponse(
471       DownloadProtectionService::GetDownloadRequestUrl(),
472       response.SerializeAsString(),
473       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
474
475   std::string hash = "hash";
476   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
477   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
478   std::vector<GURL> url_chain;
479   GURL referrer;
480
481   content::MockDownloadItem item;
482   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
483   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
484   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
485   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
486   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
487   EXPECT_CALL(item, GetTabReferrerUrl())
488       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
489   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
490   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
491   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
492   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
493   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
494       .Times(4);
495   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
496       .Times(4);
497
498   // We should not get whilelist checks for other URLs than specified below.
499   EXPECT_CALL(*sb_service_->mock_database_manager(),
500               MatchDownloadWhitelistUrl(_)).Times(0);
501   EXPECT_CALL(*sb_service_->mock_database_manager(),
502               MatchDownloadWhitelistUrl(GURL("http://www.evil.com/bla.exe")))
503       .WillRepeatedly(Return(false));
504   EXPECT_CALL(*sb_service_->mock_database_manager(),
505               MatchDownloadWhitelistUrl(GURL("http://www.google.com/a.exe")))
506       .WillRepeatedly(Return(true));
507
508   // With no referrer and just the bad url, should be marked DANGEROUS.
509   url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
510   download_service_->CheckClientDownload(
511       &item,
512       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
513                  base::Unretained(this)));
514   MessageLoop::current()->Run();
515 #if defined(OS_WIN)
516   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
517 #else
518   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
519 #endif
520
521 #if defined(OS_WIN) || defined(OS_MACOSX)
522   // OSX sends pings for evaluation purposes.
523   EXPECT_TRUE(HasClientDownloadRequest());
524   ClearClientDownloadRequest();
525 #else
526   EXPECT_FALSE(HasClientDownloadRequest());
527 #endif
528
529   // Check that the referrer is not matched against the whitelist.
530   referrer = GURL("http://www.google.com/");
531   download_service_->CheckClientDownload(
532       &item,
533       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
534                  base::Unretained(this)));
535   MessageLoop::current()->Run();
536 #if defined(OS_WIN)
537   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
538 #else
539   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
540 #endif
541
542 #if defined(OS_WIN) || defined(OS_MACOSX)
543   // OSX sends pings for evaluation purposes.
544   EXPECT_TRUE(HasClientDownloadRequest());
545   ClearClientDownloadRequest();
546 #else
547   EXPECT_FALSE(HasClientDownloadRequest());
548 #endif
549
550   // Redirect from a site shouldn't be checked either.
551   url_chain.insert(url_chain.begin(), GURL("http://www.google.com/redirect"));
552   download_service_->CheckClientDownload(
553       &item,
554       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
555                  base::Unretained(this)));
556   MessageLoop::current()->Run();
557 #if defined(OS_WIN)
558   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
559 #else
560   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
561 #endif
562
563 #if defined(OS_WIN) || defined(OS_MACOSX)
564   // OSX sends pings for evaluation purposes.
565   EXPECT_TRUE(HasClientDownloadRequest());
566   ClearClientDownloadRequest();
567 #else
568   EXPECT_FALSE(HasClientDownloadRequest());
569 #endif
570
571   // Only if the final url is whitelisted should it be SAFE.
572   url_chain.push_back(GURL("http://www.google.com/a.exe"));
573   download_service_->CheckClientDownload(
574       &item,
575       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
576                  base::Unretained(this)));
577   MessageLoop::current()->Run();
578 #if defined(OS_MACOSX)
579   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
580 #else
581   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
582 #endif
583   // TODO(grt): Make the service produce the request even when the URL is
584   // whitelisted.
585   EXPECT_FALSE(HasClientDownloadRequest());
586 }
587
588 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadFetchFailed) {
589   net::FakeURLFetcherFactory factory(NULL);
590   // HTTP request will fail.
591   factory.SetFakeResponse(
592       DownloadProtectionService::GetDownloadRequestUrl(), std::string(),
593       net::HTTP_INTERNAL_SERVER_ERROR, net::URLRequestStatus::FAILED);
594
595   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
596   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
597   std::vector<GURL> url_chain;
598   url_chain.push_back(GURL("http://www.evil.com/a.exe"));
599   GURL referrer("http://www.google.com/");
600   std::string hash = "hash";
601
602   content::MockDownloadItem item;
603   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
604   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
605   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
606   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
607   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
608   EXPECT_CALL(item, GetTabReferrerUrl())
609       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
610   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
611   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
612   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
613   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
614
615   EXPECT_CALL(*sb_service_->mock_database_manager(),
616               MatchDownloadWhitelistUrl(_))
617       .WillRepeatedly(Return(false));
618   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _));
619   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _));
620
621   download_service_->CheckClientDownload(
622       &item,
623       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
624                  base::Unretained(this)));
625   MessageLoop::current()->Run();
626   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
627 }
628
629 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadSuccess) {
630   ClientDownloadResponse response;
631   response.set_verdict(ClientDownloadResponse::SAFE);
632   net::FakeURLFetcherFactory factory(NULL);
633   // Empty response means SAFE.
634   factory.SetFakeResponse(
635       DownloadProtectionService::GetDownloadRequestUrl(),
636       response.SerializeAsString(),
637       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
638
639   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
640   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
641   std::vector<GURL> url_chain;
642   url_chain.push_back(GURL("http://www.evil.com/a.exe"));
643   GURL referrer("http://www.google.com/");
644   std::string hash = "hash";
645
646   content::MockDownloadItem item;
647   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
648   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
649   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
650   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
651   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
652   EXPECT_CALL(item, GetTabReferrerUrl())
653       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
654   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
655   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
656   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
657   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
658
659   EXPECT_CALL(*sb_service_->mock_database_manager(),
660               MatchDownloadWhitelistUrl(_))
661       .WillRepeatedly(Return(false));
662   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
663       .Times(6);
664   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
665       .Times(6);
666
667   download_service_->CheckClientDownload(
668       &item,
669       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
670                  base::Unretained(this)));
671   MessageLoop::current()->Run();
672 #if defined(OS_WIN)
673   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
674 #else
675   // On !OS_WIN, no file types are currently supported. Hence all requests to
676   // CheckClientDownload() result in a verdict of UNKNOWN.
677   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
678 #endif
679
680 #if defined(OS_WIN) || defined(OS_MACOSX)
681   // OSX sends pings for evaluation purposes.
682   EXPECT_TRUE(HasClientDownloadRequest());
683   ClearClientDownloadRequest();
684 #else
685   EXPECT_FALSE(HasClientDownloadRequest());
686 #endif
687
688   // Invalid response should result in UNKNOWN.
689   response.Clear();
690   factory.SetFakeResponse(
691       DownloadProtectionService::GetDownloadRequestUrl(),
692       response.SerializePartialAsString(),
693       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
694
695   download_service_->CheckClientDownload(
696       &item,
697       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
698                  base::Unretained(this)));
699   MessageLoop::current()->Run();
700   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
701 #if defined(OS_WIN) || defined(OS_MACOSX)
702   EXPECT_TRUE(HasClientDownloadRequest());
703   ClearClientDownloadRequest();
704 #else
705   EXPECT_FALSE(HasClientDownloadRequest());
706 #endif
707   std::string feedback_ping;
708   std::string feedback_response;
709   EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
710       item, &feedback_ping, &feedback_response));
711
712   // If the response is dangerous the result should also be marked as dangerous.
713   response.set_verdict(ClientDownloadResponse::DANGEROUS);
714   factory.SetFakeResponse(
715       DownloadProtectionService::GetDownloadRequestUrl(),
716       response.SerializeAsString(),
717       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
718
719   download_service_->CheckClientDownload(
720       &item,
721       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
722                  base::Unretained(this)));
723   MessageLoop::current()->Run();
724   EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
725       item, &feedback_ping, &feedback_response));
726 #if defined(OS_WIN)
727   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
728 #else
729   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
730 #endif
731
732 #if defined(OS_WIN) || defined(OS_MACOSX)
733   // OSX sends pings for evaluation purposes.
734   EXPECT_TRUE(HasClientDownloadRequest());
735   ClearClientDownloadRequest();
736 #else
737   EXPECT_FALSE(HasClientDownloadRequest());
738 #endif
739
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);
746
747   download_service_->CheckClientDownload(
748       &item,
749       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
750                  base::Unretained(this)));
751   MessageLoop::current()->Run();
752 #if defined(OS_WIN)
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
765
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);
773
774   download_service_->CheckClientDownload(
775       &item,
776       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
777                  base::Unretained(this)));
778   MessageLoop::current()->Run();
779 #if defined(OS_WIN)
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
789
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);
797
798   download_service_->CheckClientDownload(
799       &item,
800       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
801                  base::Unretained(this)));
802   MessageLoop::current()->Run();
803 #if defined(OS_WIN)
804   EXPECT_TRUE(IsResult(DownloadProtectionService::POTENTIALLY_UNWANTED));
805 #else
806   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
807 #endif
808
809 #if defined(OS_WIN) || defined(OS_MACOSX)
810   // OSX sends pings for evaluation purposes.
811   EXPECT_TRUE(HasClientDownloadRequest());
812   ClearClientDownloadRequest();
813 #else
814   EXPECT_FALSE(HasClientDownloadRequest());
815 #endif
816 }
817
818 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadHTTPS) {
819   ClientDownloadResponse response;
820   response.set_verdict(ClientDownloadResponse::DANGEROUS);
821   net::FakeURLFetcherFactory factory(NULL);
822   factory.SetFakeResponse(
823       DownloadProtectionService::GetDownloadRequestUrl(),
824       response.SerializeAsString(),
825       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
826
827   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
828   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
829   std::vector<GURL> url_chain;
830   url_chain.push_back(GURL("http://www.evil.com/a.exe"));
831   GURL referrer("http://www.google.com/");
832   std::string hash = "hash";
833
834   content::MockDownloadItem item;
835   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
836   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
837   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
838   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
839   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
840   EXPECT_CALL(item, GetTabReferrerUrl())
841       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
842   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
843   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
844   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
845   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
846
847   EXPECT_CALL(*sb_service_->mock_database_manager(),
848               MatchDownloadWhitelistUrl(_))
849       .WillRepeatedly(Return(false));
850   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
851       .Times(1);
852   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
853       .Times(1);
854
855   download_service_->CheckClientDownload(
856       &item,
857       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
858                  base::Unretained(this)));
859   MessageLoop::current()->Run();
860 #if defined(OS_WIN)
861   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
862 #else
863   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
864 #endif
865
866 #if defined(OS_WIN) || defined(OS_MACOSX)
867   // OSX sends pings for evaluation purposes.
868   EXPECT_TRUE(HasClientDownloadRequest());
869   ClearClientDownloadRequest();
870 #else
871   EXPECT_FALSE(HasClientDownloadRequest());
872 #endif
873 }
874
875 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadZip) {
876   ClientDownloadResponse response;
877   response.set_verdict(ClientDownloadResponse::SAFE);
878   net::FakeURLFetcherFactory factory(NULL);
879   // Empty response means SAFE.
880   factory.SetFakeResponse(
881       DownloadProtectionService::GetDownloadRequestUrl(),
882       response.SerializeAsString(),
883       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
884
885   base::ScopedTempDir download_dir;
886   ASSERT_TRUE(download_dir.CreateUniqueTempDir());
887
888   base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp")));
889   base::FilePath a_zip(FILE_PATH_LITERAL("a.zip"));
890   std::vector<GURL> url_chain;
891   url_chain.push_back(GURL("http://www.evil.com/a.zip"));
892   GURL referrer("http://www.google.com/");
893   std::string hash = "hash";
894
895   content::MockDownloadItem item;
896   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
897   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
898   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
899   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
900   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
901   EXPECT_CALL(item, GetTabReferrerUrl())
902       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
903   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
904   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
905   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
906   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
907
908   // Write out a zip archive to the temporary file.  In this case, it
909   // only contains a text file.
910   base::ScopedTempDir zip_source_dir;
911   ASSERT_TRUE(zip_source_dir.CreateUniqueTempDir());
912   std::string file_contents = "dummy file";
913   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
914       zip_source_dir.path().Append(FILE_PATH_LITERAL("file.txt")),
915       file_contents.data(), file_contents.size()));
916   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false));
917
918   download_service_->CheckClientDownload(
919       &item,
920       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
921                  base::Unretained(this)));
922   MessageLoop::current()->Run();
923   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
924   EXPECT_FALSE(HasClientDownloadRequest());
925   Mock::VerifyAndClearExpectations(sb_service_.get());
926   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
927
928   // Now check with an executable in the zip file as well.
929   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
930       zip_source_dir.path().Append(FILE_PATH_LITERAL("file.exe")),
931       file_contents.data(), file_contents.size()));
932   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false));
933
934   EXPECT_CALL(*sb_service_->mock_database_manager(),
935               MatchDownloadWhitelistUrl(_))
936       .WillRepeatedly(Return(false));
937
938   download_service_->CheckClientDownload(
939       &item,
940       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
941                  base::Unretained(this)));
942   MessageLoop::current()->Run();
943 #if defined(OS_WIN)
944   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
945 #else
946   // For !OS_WIN, no file types are currently supported. Hence the resulting
947   // verdict is UNKNOWN.
948   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
949 #endif
950
951 #if defined(OS_WIN) || defined(OS_MACOSX)
952   // OSX sends pings for evaluation purposes.
953   EXPECT_TRUE(HasClientDownloadRequest());
954   ClearClientDownloadRequest();
955 #else
956   EXPECT_FALSE(HasClientDownloadRequest());
957 #endif
958   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
959
960   // If the response is dangerous the result should also be marked as
961   // dangerous.
962   response.set_verdict(ClientDownloadResponse::DANGEROUS);
963   factory.SetFakeResponse(
964       DownloadProtectionService::GetDownloadRequestUrl(),
965       response.SerializeAsString(),
966       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
967
968   download_service_->CheckClientDownload(
969       &item,
970       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
971                  base::Unretained(this)));
972   MessageLoop::current()->Run();
973 #if defined(OS_WIN)
974   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
975 #else
976   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
977 #endif
978
979 #if defined(OS_WIN) || defined(OS_MACOSX)
980   // OSX sends pings for evaluation purposes.
981   EXPECT_TRUE(HasClientDownloadRequest());
982   ClearClientDownloadRequest();
983 #else
984   EXPECT_FALSE(HasClientDownloadRequest());
985 #endif
986   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
987 }
988
989 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadCorruptZip) {
990   base::ScopedTempDir download_dir;
991   ASSERT_TRUE(download_dir.CreateUniqueTempDir());
992
993   base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp")));
994   base::FilePath a_zip(FILE_PATH_LITERAL("a.zip"));
995   std::vector<GURL> url_chain;
996   url_chain.push_back(GURL("http://www.evil.com/a.zip"));
997   GURL referrer("http://www.google.com/");
998   std::string hash = "hash";
999
1000   content::MockDownloadItem item;
1001   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
1002   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
1003   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1004   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1005   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1006   EXPECT_CALL(item, GetTabReferrerUrl())
1007       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1008   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1009   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1010   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1011   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1012
1013   std::string file_contents = "corrupt zip file";
1014   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
1015       a_tmp, file_contents.data(), file_contents.size()));
1016
1017   download_service_->CheckClientDownload(
1018       &item,
1019       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1020                  base::Unretained(this)));
1021   MessageLoop::current()->Run();
1022   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1023   EXPECT_FALSE(HasClientDownloadRequest());
1024   Mock::VerifyAndClearExpectations(sb_service_.get());
1025   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
1026 }
1027
1028 TEST_F(DownloadProtectionServiceTest, CheckClientCrxDownloadSuccess) {
1029   ClientDownloadResponse response;
1030   // Even if the server verdict is dangerous we should return SAFE because
1031   // DownloadProtectionService::IsSupportedDownload() will return false
1032   // for crx downloads.
1033   response.set_verdict(ClientDownloadResponse::DANGEROUS);
1034   net::FakeURLFetcherFactory factory(NULL);
1035   // Empty response means SAFE.
1036   factory.SetFakeResponse(
1037       DownloadProtectionService::GetDownloadRequestUrl(),
1038       response.SerializeAsString(),
1039       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
1040
1041   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
1042   base::FilePath a_crx(FILE_PATH_LITERAL("a.crx"));
1043   std::vector<GURL> url_chain;
1044   url_chain.push_back(GURL("http://www.evil.com/a.crx"));
1045   GURL referrer("http://www.google.com/");
1046   std::string hash = "hash";
1047
1048   content::MockDownloadItem item;
1049   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
1050   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_crx));
1051   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1052   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1053   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1054   EXPECT_CALL(item, GetTabReferrerUrl())
1055       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1056   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1057   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1058   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1059   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1060
1061   EXPECT_CALL(*sb_service_->mock_database_manager(),
1062               MatchDownloadWhitelistUrl(_))
1063       .WillRepeatedly(Return(false));
1064   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
1065       .Times(1);
1066   EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
1067       .Times(1);
1068
1069   EXPECT_FALSE(download_service_->IsSupportedDownload(item, a_crx));
1070   download_service_->CheckClientDownload(
1071       &item,
1072       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1073                  base::Unretained(this)));
1074   MessageLoop::current()->Run();
1075   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1076 }
1077
1078 #if defined(OS_MACOSX)
1079 // TODO(mattm): remove this (see crbug.com/414834).
1080 TEST_F(DownloadProtectionServiceTest,
1081        CheckClientDownloadPingOnOSXRequiresFieldTrial) {
1082   // Clear the field trial that was set in SetUp().
1083   field_trial_list_.reset();
1084
1085   net::TestURLFetcherFactory factory;
1086
1087   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1088   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1089   std::vector<GURL> url_chain;
1090   url_chain.push_back(GURL("http://www.google.com/"));
1091   url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1092   GURL referrer("http://www.google.com/");
1093   std::string hash = "hash";
1094   std::string remote_address = "10.11.12.13";
1095
1096   content::MockDownloadItem item;
1097   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1098   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1099   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1100   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1101   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1102   EXPECT_CALL(item, GetTabReferrerUrl())
1103       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1104   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1105   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1106   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1107   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1108
1109   EXPECT_CALL(*sb_service_->mock_database_manager(),
1110               MatchDownloadWhitelistUrl(_))
1111       .WillRepeatedly(Return(false));
1112   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
1113       .WillOnce(SetCertificateContents("dummy cert data"));
1114   EXPECT_CALL(*binary_feature_extractor_.get(),
1115               ExtractImageHeaders(tmp_path, _))
1116       .WillOnce(SetDosHeaderContents("dummy dos header"));
1117   download_service_->CheckClientDownload(
1118       &item,
1119       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1120                  base::Unretained(this)));
1121
1122   // SendRequest is not called.  Wait for FinishRequest to call our callback.
1123   MessageLoop::current()->Run();
1124   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1125   EXPECT_EQ(NULL, fetcher);
1126   EXPECT_FALSE(HasClientDownloadRequest());
1127 }
1128 #endif
1129
1130 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadValidateRequest) {
1131   net::TestURLFetcherFactory factory;
1132
1133   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1134   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1135   std::vector<GURL> url_chain;
1136   url_chain.push_back(GURL("http://www.google.com/"));
1137   url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1138   GURL referrer("http://www.google.com/");
1139   std::string hash = "hash";
1140   std::string remote_address = "10.11.12.13";
1141
1142   content::MockDownloadItem item;
1143   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1144   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1145   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1146   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1147   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1148   EXPECT_CALL(item, GetTabReferrerUrl())
1149       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1150   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1151   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1152   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1153   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1154
1155   EXPECT_CALL(*sb_service_->mock_database_manager(),
1156               MatchDownloadWhitelistUrl(_))
1157       .WillRepeatedly(Return(false));
1158   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
1159       .WillOnce(SetCertificateContents("dummy cert data"));
1160   EXPECT_CALL(*binary_feature_extractor_.get(),
1161               ExtractImageHeaders(tmp_path, _))
1162       .WillOnce(SetDosHeaderContents("dummy dos header"));
1163   download_service_->CheckClientDownload(
1164       &item,
1165       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1166                  base::Unretained(this)));
1167
1168 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1169   // SendRequest is not called.  Wait for FinishRequest to call our callback.
1170   MessageLoop::current()->Run();
1171   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1172   EXPECT_EQ(NULL, fetcher);
1173   EXPECT_FALSE(HasClientDownloadRequest());
1174 #else
1175   // Run the message loop(s) until SendRequest is called.
1176   FlushThreadMessageLoops();
1177   EXPECT_TRUE(HasClientDownloadRequest());
1178   ClearClientDownloadRequest();
1179   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1180   ASSERT_TRUE(fetcher);
1181   ClientDownloadRequest request;
1182   EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1183   EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1184   EXPECT_EQ(hash, request.digests().sha256());
1185   EXPECT_EQ(item.GetReceivedBytes(), request.length());
1186   EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1187   EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1188   EXPECT_EQ(2, request.resources_size());
1189   EXPECT_TRUE(RequestContainsResource(request,
1190                                       ClientDownloadRequest::DOWNLOAD_REDIRECT,
1191                                       "http://www.google.com/", ""));
1192   EXPECT_TRUE(RequestContainsResource(request,
1193                                       ClientDownloadRequest::DOWNLOAD_URL,
1194                                       "http://www.google.com/bla.exe",
1195                                       referrer.spec()));
1196   EXPECT_TRUE(request.has_signature());
1197   ASSERT_EQ(1, request.signature().certificate_chain_size());
1198   const ClientDownloadRequest_CertificateChain& chain =
1199       request.signature().certificate_chain(0);
1200   ASSERT_EQ(1, chain.element_size());
1201   EXPECT_EQ("dummy cert data", chain.element(0).certificate());
1202   EXPECT_TRUE(request.has_image_headers());
1203   const ClientDownloadRequest_ImageHeaders& headers =
1204       request.image_headers();
1205   EXPECT_TRUE(headers.has_pe_headers());
1206   EXPECT_TRUE(headers.pe_headers().has_dos_header());
1207   EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
1208
1209   // Simulate the request finishing.
1210   base::MessageLoop::current()->PostTask(
1211       FROM_HERE,
1212       base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1213                  base::Unretained(this), fetcher));
1214   MessageLoop::current()->Run();
1215 #endif
1216 }
1217
1218 // Similar to above, but with an unsigned binary.
1219 TEST_F(DownloadProtectionServiceTest,
1220        CheckClientDownloadValidateRequestNoSignature) {
1221   net::TestURLFetcherFactory factory;
1222
1223   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1224   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1225   std::vector<GURL> url_chain;
1226   url_chain.push_back(GURL("http://www.google.com/"));
1227   url_chain.push_back(GURL("ftp://www.google.com/bla.exe"));
1228   GURL referrer("http://www.google.com/");
1229   std::string hash = "hash";
1230   std::string remote_address = "10.11.12.13";
1231
1232   content::MockDownloadItem item;
1233   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1234   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1235   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1236   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1237   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1238   EXPECT_CALL(item, GetTabReferrerUrl())
1239       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1240   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1241   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1242   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1243   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1244
1245   EXPECT_CALL(*sb_service_->mock_database_manager(),
1246               MatchDownloadWhitelistUrl(_))
1247       .WillRepeatedly(Return(false));
1248   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1249   EXPECT_CALL(*binary_feature_extractor_.get(),
1250               ExtractImageHeaders(tmp_path, _));
1251   download_service_->CheckClientDownload(
1252       &item,
1253       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1254                  base::Unretained(this)));
1255
1256 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1257   // SendRequest is not called.  Wait for FinishRequest to call our callback.
1258   MessageLoop::current()->Run();
1259   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1260   EXPECT_EQ(NULL, fetcher);
1261   EXPECT_FALSE(HasClientDownloadRequest());
1262 #else
1263   // Run the message loop(s) until SendRequest is called.
1264   FlushThreadMessageLoops();
1265   EXPECT_TRUE(HasClientDownloadRequest());
1266   ClearClientDownloadRequest();
1267   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1268   ASSERT_TRUE(fetcher);
1269   ClientDownloadRequest request;
1270   EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1271   EXPECT_EQ("ftp://www.google.com/bla.exe", request.url());
1272   EXPECT_EQ(hash, request.digests().sha256());
1273   EXPECT_EQ(item.GetReceivedBytes(), request.length());
1274   EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1275   EXPECT_EQ(2, request.resources_size());
1276   EXPECT_TRUE(RequestContainsResource(request,
1277                                       ClientDownloadRequest::DOWNLOAD_REDIRECT,
1278                                       "http://www.google.com/", ""));
1279   EXPECT_TRUE(RequestContainsResource(request,
1280                                       ClientDownloadRequest::DOWNLOAD_URL,
1281                                       "ftp://www.google.com/bla.exe",
1282                                       referrer.spec()));
1283   EXPECT_TRUE(request.has_signature());
1284   EXPECT_EQ(0, request.signature().certificate_chain_size());
1285
1286   // Simulate the request finishing.
1287   base::MessageLoop::current()->PostTask(
1288       FROM_HERE,
1289       base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1290                  base::Unretained(this), fetcher));
1291   MessageLoop::current()->Run();
1292 #endif
1293 }
1294
1295 // Similar to above, but with tab history.
1296 TEST_F(DownloadProtectionServiceTest,
1297        CheckClientDownloadValidateRequestTabHistory) {
1298   net::TestURLFetcherFactory factory;
1299
1300   base::ScopedTempDir profile_dir;
1301   ASSERT_TRUE(profile_dir.CreateUniqueTempDir());
1302   TestingProfile profile(profile_dir.path());
1303   ASSERT_TRUE(
1304       profile.CreateHistoryService(true /* delete_file */, false /* no_db */));
1305
1306   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
1307   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
1308   std::vector<GURL> url_chain;
1309   url_chain.push_back(GURL("http://www.google.com/"));
1310   url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1311   GURL referrer("http://www.google.com/");
1312   GURL tab_url("http://tab.com/final");
1313   GURL tab_referrer("http://tab.com/referrer");
1314   std::string hash = "hash";
1315   std::string remote_address = "10.11.12.13";
1316
1317   content::MockDownloadItem item;
1318   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1319   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1320   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1321   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1322   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
1323   EXPECT_CALL(item, GetTabReferrerUrl())
1324       .WillRepeatedly(ReturnRef(tab_referrer));
1325   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1326   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1327   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1328   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
1329   EXPECT_CALL(item, GetBrowserContext()).WillRepeatedly(Return(&profile));
1330   EXPECT_CALL(*sb_service_->mock_database_manager(),
1331               MatchDownloadWhitelistUrl(_))
1332       .WillRepeatedly(Return(false));
1333   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
1334       .WillRepeatedly(SetCertificateContents("dummy cert data"));
1335   EXPECT_CALL(*binary_feature_extractor_.get(),
1336               ExtractImageHeaders(tmp_path, _))
1337       .WillRepeatedly(SetDosHeaderContents("dummy dos header"));
1338
1339   // First test with no history match for the tab URL.
1340   {
1341     TestURLFetcherWatcher fetcher_watcher(&factory);
1342     download_service_->CheckClientDownload(
1343         &item,
1344         base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1345                    base::Unretained(this)));
1346
1347 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1348     // SendRequest is not called.  Wait for FinishRequest to call our callback.
1349     MessageLoop::current()->Run();
1350     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1351     EXPECT_EQ(NULL, fetcher);
1352     EXPECT_FALSE(HasClientDownloadRequest());
1353 #else
1354     EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
1355     EXPECT_TRUE(HasClientDownloadRequest());
1356     ClearClientDownloadRequest();
1357     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1358     ASSERT_TRUE(fetcher);
1359     ClientDownloadRequest request;
1360     EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1361     EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1362     EXPECT_EQ(hash, request.digests().sha256());
1363     EXPECT_EQ(item.GetReceivedBytes(), request.length());
1364     EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1365     EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1366     EXPECT_EQ(3, request.resources_size());
1367     EXPECT_TRUE(
1368         RequestContainsResource(request,
1369                                 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1370                                 "http://www.google.com/",
1371                                 ""));
1372     EXPECT_TRUE(RequestContainsResource(request,
1373                                         ClientDownloadRequest::DOWNLOAD_URL,
1374                                         "http://www.google.com/bla.exe",
1375                                         referrer.spec()));
1376     EXPECT_TRUE(RequestContainsResource(request,
1377                                         ClientDownloadRequest::TAB_URL,
1378                                         tab_url.spec(),
1379                                         tab_referrer.spec()));
1380     EXPECT_TRUE(request.has_signature());
1381     ASSERT_EQ(1, request.signature().certificate_chain_size());
1382     const ClientDownloadRequest_CertificateChain& chain =
1383         request.signature().certificate_chain(0);
1384     ASSERT_EQ(1, chain.element_size());
1385     EXPECT_EQ("dummy cert data", chain.element(0).certificate());
1386     EXPECT_TRUE(request.has_image_headers());
1387     const ClientDownloadRequest_ImageHeaders& headers =
1388         request.image_headers();
1389     EXPECT_TRUE(headers.has_pe_headers());
1390     EXPECT_TRUE(headers.pe_headers().has_dos_header());
1391     EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
1392
1393     // Simulate the request finishing.
1394     base::MessageLoop::current()->PostTask(
1395         FROM_HERE,
1396         base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1397                    base::Unretained(this),
1398                    fetcher));
1399     MessageLoop::current()->Run();
1400 #endif
1401   }
1402
1403   // Now try with a history match.
1404   {
1405     history::RedirectList redirects;
1406     redirects.push_back(GURL("http://tab.com/ref1"));
1407     redirects.push_back(GURL("http://tab.com/ref2"));
1408     redirects.push_back(tab_url);
1409     HistoryServiceFactory::GetForProfile(&profile, Profile::EXPLICIT_ACCESS)
1410         ->AddPage(tab_url,
1411                   base::Time::Now(),
1412                   reinterpret_cast<history::ContextID>(1),
1413                   0,
1414                   GURL(),
1415                   redirects,
1416                   ui::PAGE_TRANSITION_TYPED,
1417                   history::SOURCE_BROWSED,
1418                   false);
1419
1420     TestURLFetcherWatcher fetcher_watcher(&factory);
1421     download_service_->CheckClientDownload(
1422         &item,
1423         base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1424                    base::Unretained(this)));
1425 #if !defined(OS_WIN) && !defined(OS_MACOSX)
1426     // SendRequest is not called.  Wait for FinishRequest to call our callback.
1427     MessageLoop::current()->Run();
1428     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1429     EXPECT_EQ(NULL, fetcher);
1430     EXPECT_FALSE(HasClientDownloadRequest());
1431 #else
1432     EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
1433     EXPECT_TRUE(HasClientDownloadRequest());
1434     ClearClientDownloadRequest();
1435     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
1436     ASSERT_TRUE(fetcher);
1437     ClientDownloadRequest request;
1438     EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
1439     EXPECT_EQ("http://www.google.com/bla.exe", request.url());
1440     EXPECT_EQ(hash, request.digests().sha256());
1441     EXPECT_EQ(item.GetReceivedBytes(), request.length());
1442     EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
1443     EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
1444     EXPECT_EQ(5, request.resources_size());
1445     EXPECT_TRUE(
1446         RequestContainsResource(request,
1447                                 ClientDownloadRequest::DOWNLOAD_REDIRECT,
1448                                 "http://www.google.com/",
1449                                 ""));
1450     EXPECT_TRUE(RequestContainsResource(request,
1451                                         ClientDownloadRequest::DOWNLOAD_URL,
1452                                         "http://www.google.com/bla.exe",
1453                                         referrer.spec()));
1454     EXPECT_TRUE(RequestContainsResource(request,
1455                                         ClientDownloadRequest::TAB_REDIRECT,
1456                                         "http://tab.com/ref1",
1457                                         ""));
1458     EXPECT_TRUE(RequestContainsResource(request,
1459                                         ClientDownloadRequest::TAB_REDIRECT,
1460                                         "http://tab.com/ref2",
1461                                         ""));
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
1473     // Simulate the request finishing.
1474     base::MessageLoop::current()->PostTask(
1475         FROM_HERE,
1476         base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
1477                    base::Unretained(this),
1478                    fetcher));
1479     MessageLoop::current()->Run();
1480 #endif
1481   }
1482 }
1483
1484 TEST_F(DownloadProtectionServiceTest, TestCheckDownloadUrl) {
1485   std::vector<GURL> url_chain;
1486   url_chain.push_back(GURL("http://www.google.com/"));
1487   url_chain.push_back(GURL("http://www.google.com/bla.exe"));
1488   GURL referrer("http://www.google.com/");
1489   std::string hash = "hash";
1490
1491   content::MockDownloadItem item;
1492   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1493   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1494   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1495
1496   // CheckDownloadURL returns immediately which means the client object callback
1497   // will never be called.  Nevertheless the callback provided to
1498   // CheckClientDownload must still be called.
1499   EXPECT_CALL(*sb_service_->mock_database_manager(),
1500               CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1501       .WillOnce(Return(true));
1502   download_service_->CheckDownloadUrl(
1503       item,
1504       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1505                  base::Unretained(this)));
1506   MessageLoop::current()->Run();
1507   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1508   Mock::VerifyAndClearExpectations(sb_service_.get());
1509
1510   EXPECT_CALL(*sb_service_->mock_database_manager(),
1511               CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1512       .WillOnce(DoAll(CheckDownloadUrlDone(SB_THREAT_TYPE_SAFE),
1513                       Return(false)));
1514   download_service_->CheckDownloadUrl(
1515       item,
1516       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1517                  base::Unretained(this)));
1518   MessageLoop::current()->Run();
1519   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1520   Mock::VerifyAndClearExpectations(sb_service_.get());
1521
1522   EXPECT_CALL(*sb_service_->mock_database_manager(),
1523               CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
1524       .WillOnce(DoAll(
1525           CheckDownloadUrlDone(SB_THREAT_TYPE_URL_MALWARE),
1526           Return(false)));
1527   download_service_->CheckDownloadUrl(
1528       item,
1529       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1530                  base::Unretained(this)));
1531   MessageLoop::current()->Run();
1532   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
1533   Mock::VerifyAndClearExpectations(sb_service_.get());
1534
1535   EXPECT_CALL(*sb_service_->mock_database_manager(),
1536               CheckDownloadUrl(ContainerEq(url_chain),
1537                                NotNull()))
1538       .WillOnce(DoAll(
1539           CheckDownloadUrlDone(SB_THREAT_TYPE_BINARY_MALWARE_URL),
1540           Return(false)));
1541   download_service_->CheckDownloadUrl(
1542       item,
1543       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1544                  base::Unretained(this)));
1545   MessageLoop::current()->Run();
1546   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
1547 }
1548
1549 TEST_F(DownloadProtectionServiceTest, TestDownloadRequestTimeout) {
1550   net::TestURLFetcherFactory factory;
1551
1552   std::vector<GURL> url_chain;
1553   url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1554   GURL referrer("http://www.google.com/");
1555   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1556   base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1557   std::string hash = "hash";
1558
1559   content::MockDownloadItem item;
1560   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1561   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
1562   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1563   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1564   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1565   EXPECT_CALL(item, GetTabReferrerUrl())
1566       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1567   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1568   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1569   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1570   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1571
1572   EXPECT_CALL(*sb_service_->mock_database_manager(),
1573               MatchDownloadWhitelistUrl(_))
1574       .WillRepeatedly(Return(false));
1575   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1576   EXPECT_CALL(*binary_feature_extractor_.get(),
1577               ExtractImageHeaders(tmp_path, _));
1578
1579   download_service_->download_request_timeout_ms_ = 10;
1580   download_service_->CheckClientDownload(
1581       &item,
1582       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1583                  base::Unretained(this)));
1584
1585   // The request should time out because the HTTP request hasn't returned
1586   // anything yet.
1587   MessageLoop::current()->Run();
1588   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1589 #if defined(OS_WIN) || defined(OS_MACOSX)
1590   EXPECT_TRUE(HasClientDownloadRequest());
1591   ClearClientDownloadRequest();
1592 #else
1593   EXPECT_FALSE(HasClientDownloadRequest());
1594 #endif
1595 }
1596
1597 TEST_F(DownloadProtectionServiceTest, TestDownloadItemDestroyed) {
1598   net::TestURLFetcherFactory factory;
1599
1600   std::vector<GURL> url_chain;
1601   url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1602   GURL referrer("http://www.google.com/");
1603   GURL tab_url("http://www.google.com/tab");
1604   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1605   base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1606   std::string hash = "hash";
1607
1608   {
1609     content::MockDownloadItem item;
1610     EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1611     EXPECT_CALL(item, GetTargetFilePath())
1612         .WillRepeatedly(ReturnRef(final_path));
1613     EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1614     EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1615     EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
1616     EXPECT_CALL(item, GetTabReferrerUrl())
1617         .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1618     EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
1619     EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
1620     EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
1621     EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
1622
1623     EXPECT_CALL(*sb_service_->mock_database_manager(),
1624                 MatchDownloadWhitelistUrl(_))
1625         .WillRepeatedly(Return(false));
1626     EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1627     EXPECT_CALL(*binary_feature_extractor_.get(),
1628                 ExtractImageHeaders(tmp_path, _));
1629
1630     download_service_->CheckClientDownload(
1631         &item,
1632         base::Bind(&DownloadProtectionServiceTest::SyncCheckDoneCallback,
1633                    base::Unretained(this)));
1634     // MockDownloadItem going out of scope triggers the OnDownloadDestroyed
1635     // notification.
1636   }
1637
1638   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1639   EXPECT_FALSE(HasClientDownloadRequest());
1640 }
1641
1642 TEST_F(DownloadProtectionServiceTest,
1643        TestDownloadItemDestroyedDuringWhitelistCheck) {
1644   net::TestURLFetcherFactory factory;
1645
1646   std::vector<GURL> url_chain;
1647   url_chain.push_back(GURL("http://www.evil.com/bla.exe"));
1648   GURL referrer("http://www.google.com/");
1649   GURL tab_url("http://www.google.com/tab");
1650   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp"));
1651   base::FilePath final_path(FILE_PATH_LITERAL("a.exe"));
1652   std::string hash = "hash";
1653
1654   scoped_ptr<content::MockDownloadItem> item(new content::MockDownloadItem);
1655   EXPECT_CALL(*item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
1656   EXPECT_CALL(*item, GetTargetFilePath())
1657       .WillRepeatedly(ReturnRef(final_path));
1658   EXPECT_CALL(*item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
1659   EXPECT_CALL(*item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
1660   EXPECT_CALL(*item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
1661   EXPECT_CALL(*item, GetTabReferrerUrl())
1662       .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
1663   EXPECT_CALL(*item, GetHash()).WillRepeatedly(ReturnRef(hash));
1664   EXPECT_CALL(*item, GetReceivedBytes()).WillRepeatedly(Return(100));
1665   EXPECT_CALL(*item, HasUserGesture()).WillRepeatedly(Return(true));
1666   EXPECT_CALL(*item, GetRemoteAddress()).WillRepeatedly(Return(""));
1667
1668   EXPECT_CALL(*sb_service_->mock_database_manager(),
1669               MatchDownloadWhitelistUrl(_))
1670       .WillRepeatedly(Invoke([&item](const GURL&) {
1671         item.reset();
1672         return false;
1673       }));
1674   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
1675   EXPECT_CALL(*binary_feature_extractor_.get(),
1676               ExtractImageHeaders(tmp_path, _));
1677
1678   download_service_->CheckClientDownload(
1679       item.get(),
1680       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
1681                  base::Unretained(this)));
1682
1683   MessageLoop::current()->Run();
1684   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
1685   EXPECT_FALSE(HasClientDownloadRequest());
1686 }
1687
1688 TEST_F(DownloadProtectionServiceTest, GetCertificateWhitelistStrings) {
1689   // We'll pass this cert in as the "issuer", even though it isn't really
1690   // used to sign the certs below.  GetCertificateWhitelistStirngs doesn't care
1691   // about this.
1692   scoped_refptr<net::X509Certificate> issuer_cert(
1693       ReadTestCertificate("issuer.pem"));
1694   ASSERT_TRUE(issuer_cert.get());
1695   std::string cert_base = "cert/" + base::HexEncode(
1696       issuer_cert->fingerprint().data,
1697       sizeof(issuer_cert->fingerprint().data));
1698
1699   scoped_refptr<net::X509Certificate> cert(ReadTestCertificate("test_cn.pem"));
1700   ASSERT_TRUE(cert.get());
1701   std::vector<std::string> whitelist_strings;
1702   GetCertificateWhitelistStrings(
1703       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1704   // This also tests escaping of characters in the certificate attributes.
1705   EXPECT_THAT(whitelist_strings, ElementsAre(
1706       cert_base + "/CN=subject%2F%251"));
1707
1708   cert = ReadTestCertificate("test_cn_o.pem");
1709   ASSERT_TRUE(cert.get());
1710   whitelist_strings.clear();
1711   GetCertificateWhitelistStrings(
1712       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1713   EXPECT_THAT(whitelist_strings,
1714               ElementsAre(cert_base + "/CN=subject",
1715                           cert_base + "/CN=subject/O=org",
1716                           cert_base + "/O=org"));
1717
1718   cert = ReadTestCertificate("test_cn_o_ou.pem");
1719   ASSERT_TRUE(cert.get());
1720   whitelist_strings.clear();
1721   GetCertificateWhitelistStrings(
1722       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1723   EXPECT_THAT(whitelist_strings,
1724               ElementsAre(cert_base + "/CN=subject",
1725                           cert_base + "/CN=subject/O=org",
1726                           cert_base + "/CN=subject/O=org/OU=unit",
1727                           cert_base + "/CN=subject/OU=unit",
1728                           cert_base + "/O=org",
1729                           cert_base + "/O=org/OU=unit",
1730                           cert_base + "/OU=unit"));
1731
1732   cert = ReadTestCertificate("test_cn_ou.pem");
1733   ASSERT_TRUE(cert.get());
1734   whitelist_strings.clear();
1735   GetCertificateWhitelistStrings(
1736       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1737   EXPECT_THAT(whitelist_strings,
1738               ElementsAre(cert_base + "/CN=subject",
1739                           cert_base + "/CN=subject/OU=unit",
1740                           cert_base + "/OU=unit"));
1741
1742   cert = ReadTestCertificate("test_o.pem");
1743   ASSERT_TRUE(cert.get());
1744   whitelist_strings.clear();
1745   GetCertificateWhitelistStrings(
1746       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1747   EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/O=org"));
1748
1749   cert = ReadTestCertificate("test_o_ou.pem");
1750   ASSERT_TRUE(cert.get());
1751   whitelist_strings.clear();
1752   GetCertificateWhitelistStrings(
1753       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1754   EXPECT_THAT(whitelist_strings,
1755               ElementsAre(cert_base + "/O=org",
1756                           cert_base + "/O=org/OU=unit",
1757                           cert_base + "/OU=unit"));
1758
1759   cert = ReadTestCertificate("test_ou.pem");
1760   ASSERT_TRUE(cert.get());
1761   whitelist_strings.clear();
1762   GetCertificateWhitelistStrings(
1763       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1764   EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/OU=unit"));
1765
1766   cert = ReadTestCertificate("test_c.pem");
1767   ASSERT_TRUE(cert.get());
1768   whitelist_strings.clear();
1769   GetCertificateWhitelistStrings(
1770       *cert.get(), *issuer_cert.get(), &whitelist_strings);
1771   EXPECT_THAT(whitelist_strings, ElementsAre());
1772 }
1773 }  // namespace safe_browsing