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