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