| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/safe_browsing/download_protection_service.h" | 
 |  | 
 | #include <stddef.h> | 
 | #include <stdint.h> | 
 | #include <map> | 
 | #include <string> | 
 |  | 
 | #include "base/base_paths.h" | 
 | #include "base/bind.h" | 
 | #include "base/callback.h" | 
 | #include "base/command_line.h" | 
 | #include "base/files/file_path.h" | 
 | #include "base/files/file_util.h" | 
 | #include "base/files/scoped_temp_dir.h" | 
 | #include "base/macros.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/scoped_ptr.h" | 
 | #include "base/message_loop/message_loop.h" | 
 | #include "base/path_service.h" | 
 | #include "base/prefs/pref_service.h" | 
 | #include "base/run_loop.h" | 
 | #include "base/strings/string_number_conversions.h" | 
 | #include "base/threading/sequenced_worker_pool.h" | 
 | #include "chrome/browser/history/history_service_factory.h" | 
 | #include "chrome/browser/safe_browsing/download_feedback_service.h" | 
 | #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h" | 
 | #include "chrome/browser/safe_browsing/local_database_manager.h" | 
 | #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 
 | #include "chrome/common/chrome_switches.h" | 
 | #include "chrome/common/pref_names.h" | 
 | #include "chrome/common/safe_browsing/binary_feature_extractor.h" | 
 | #include "chrome/common/safe_browsing/csd.pb.h" | 
 | #include "chrome/test/base/testing_profile.h" | 
 | #include "components/history/core/browser/history_service.h" | 
 | #include "components/safe_browsing_db/database_manager.h" | 
 | #include "components/safe_browsing_db/test_database_manager.h" | 
 | #include "content/public/browser/download_danger_type.h" | 
 | #include "content/public/browser/page_navigator.h" | 
 | #include "content/public/test/mock_download_item.h" | 
 | #include "content/public/test/test_browser_thread_bundle.h" | 
 | #include "content/public/test/test_utils.h" | 
 | #include "net/base/url_util.h" | 
 | #include "net/cert/x509_certificate.h" | 
 | #include "net/http/http_status_code.h" | 
 | #include "net/url_request/test_url_fetcher_factory.h" | 
 | #include "net/url_request/url_fetcher_delegate.h" | 
 | #include "net/url_request/url_request_status.h" | 
 | #include "testing/gmock/include/gmock/gmock.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 | #include "third_party/zlib/google/zip.h" | 
 | #include "url/gurl.h" | 
 |  | 
 | using ::testing::Assign; | 
 | using ::testing::ContainerEq; | 
 | using ::testing::DoAll; | 
 | using ::testing::ElementsAre; | 
 | using ::testing::Invoke; | 
 | using ::testing::Mock; | 
 | using ::testing::NotNull; | 
 | using ::testing::Return; | 
 | using ::testing::ReturnRef; | 
 | using ::testing::SaveArg; | 
 | using ::testing::StrictMock; | 
 | using ::testing::_; | 
 | using base::MessageLoop; | 
 | using content::BrowserThread; | 
 | namespace safe_browsing { | 
 | namespace { | 
 | // A SafeBrowsingDatabaseManager implementation that returns a fixed result for | 
 | // a given URL. | 
 | class MockSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager { | 
 |  public: | 
 |   MockSafeBrowsingDatabaseManager() {} | 
 |  | 
 |   MOCK_METHOD1(MatchDownloadWhitelistUrl, bool(const GURL&)); | 
 |   MOCK_METHOD1(MatchDownloadWhitelistString, bool(const std::string&)); | 
 |   MOCK_METHOD2(CheckDownloadUrl, bool( | 
 |       const std::vector<GURL>& url_chain, | 
 |       SafeBrowsingDatabaseManager::Client* client)); | 
 |  | 
 |  private: | 
 |   virtual ~MockSafeBrowsingDatabaseManager() {} | 
 |   DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager); | 
 | }; | 
 |  | 
 | class FakeSafeBrowsingService : public SafeBrowsingService { | 
 |  public: | 
 |   FakeSafeBrowsingService() { } | 
 |  | 
 |   // Returned pointer has the same lifespan as the database_manager_ refcounted | 
 |   // object. | 
 |   MockSafeBrowsingDatabaseManager* mock_database_manager() { | 
 |     return mock_database_manager_; | 
 |   } | 
 |  | 
 |  protected: | 
 |   ~FakeSafeBrowsingService() override {} | 
 |  | 
 |   SafeBrowsingDatabaseManager* CreateDatabaseManager() override { | 
 |     mock_database_manager_ = new MockSafeBrowsingDatabaseManager(); | 
 |     return mock_database_manager_; | 
 |   } | 
 |  | 
 |   IncidentReportingService* CreateIncidentReportingService() override { | 
 |     return new IncidentReportingService(nullptr, nullptr); | 
 |   } | 
 |  | 
 |   SafeBrowsingProtocolManagerDelegate* GetProtocolManagerDelegate() override { | 
 |     // Our SafeBrowsingDatabaseManager doesn't implement this delegate. | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   void RegisterAllDelayedAnalysis() override {} | 
 |  | 
 |  private: | 
 |   MockSafeBrowsingDatabaseManager* mock_database_manager_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService); | 
 | }; | 
 |  | 
 | class MockBinaryFeatureExtractor : public BinaryFeatureExtractor { | 
 |  public: | 
 |   MockBinaryFeatureExtractor() {} | 
 |   MOCK_METHOD2(CheckSignature, void(const base::FilePath&, | 
 |                                     ClientDownloadRequest_SignatureInfo*)); | 
 |   MOCK_METHOD4(ExtractImageFeatures, bool( | 
 |       const base::FilePath&, | 
 |       ExtractHeadersOption, | 
 |       ClientDownloadRequest_ImageHeaders*, | 
 |       google::protobuf::RepeatedPtrField<std::string>*)); | 
 |  | 
 |  protected: | 
 |   virtual ~MockBinaryFeatureExtractor() {} | 
 |  | 
 |  private: | 
 |   DISALLOW_COPY_AND_ASSIGN(MockBinaryFeatureExtractor); | 
 | }; | 
 |  | 
 | class TestURLFetcherWatcher : public net::TestURLFetcherDelegateForTests { | 
 |  public: | 
 |   explicit TestURLFetcherWatcher(net::TestURLFetcherFactory* factory) | 
 |       : factory_(factory), fetcher_id_(-1) { | 
 |     factory_->SetDelegateForTests(this); | 
 |   } | 
 |   ~TestURLFetcherWatcher() { | 
 |     factory_->SetDelegateForTests(NULL); | 
 |   } | 
 |  | 
 |   // TestURLFetcherDelegateForTests impl: | 
 |   void OnRequestStart(int fetcher_id) override { | 
 |     fetcher_id_ = fetcher_id; | 
 |     run_loop_.Quit(); | 
 |   } | 
 |   void OnChunkUpload(int fetcher_id) override {} | 
 |   void OnRequestEnd(int fetcher_id) override {} | 
 |  | 
 |   int WaitForRequest() { | 
 |     run_loop_.Run(); | 
 |     return fetcher_id_; | 
 |   } | 
 |  | 
 |  private: | 
 |   net::TestURLFetcherFactory* factory_; | 
 |   int fetcher_id_; | 
 |   base::RunLoop run_loop_; | 
 | }; | 
 | }  // namespace | 
 |  | 
 | ACTION_P(SetCertificateContents, contents) { | 
 |   arg1->add_certificate_chain()->add_element()->set_certificate(contents); | 
 | } | 
 |  | 
 | ACTION_P(SetDosHeaderContents, contents) { | 
 |   arg2->mutable_pe_headers()->set_dos_header(contents); | 
 |   return true; | 
 | } | 
 |  | 
 | ACTION_P(TrustSignature, certificate_file) { | 
 |   arg1->set_trusted(true); | 
 |   // Add a certificate chain.  Note that we add the certificate twice so that | 
 |   // it appears as its own issuer. | 
 |   std::string cert_data; | 
 |   ASSERT_TRUE(base::ReadFileToString(certificate_file, &cert_data)); | 
 |   ClientDownloadRequest_CertificateChain* chain = | 
 |       arg1->add_certificate_chain(); | 
 |   chain->add_element()->set_certificate(cert_data); | 
 |   chain->add_element()->set_certificate(cert_data); | 
 | } | 
 |  | 
 | // We can't call OnSafeBrowsingResult directly because SafeBrowsingCheck does | 
 | // not have any copy constructor which means it can't be stored in a callback | 
 | // easily.  Note: check will be deleted automatically when the callback is | 
 | // deleted. | 
 | void OnSafeBrowsingResult( | 
 |     LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck* check) { | 
 |   check->OnSafeBrowsingResult(); | 
 | } | 
 |  | 
 | ACTION_P(CheckDownloadUrlDone, threat_type) { | 
 |   // TODO(nparker): Remove use of SafeBrowsingCheck and instead call | 
 |   // client->OnCheckDownloadUrlResult(..) directly. | 
 |   LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck* check = | 
 |       new LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck( | 
 |           arg0, std::vector<SBFullHash>(), arg1, BINURL, | 
 |           std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL)); | 
 |   for (size_t i = 0; i < check->url_results.size(); ++i) | 
 |     check->url_results[i] = threat_type; | 
 |   BrowserThread::PostTask(BrowserThread::IO, | 
 |                           FROM_HERE, | 
 |                           base::Bind(&OnSafeBrowsingResult, | 
 |                                      base::Owned(check))); | 
 | } | 
 |  | 
 | class DownloadProtectionServiceTest : public testing::Test { | 
 |  protected: | 
 |   DownloadProtectionServiceTest() | 
 |       : test_browser_thread_bundle_( | 
 |             content::TestBrowserThreadBundle::IO_MAINLOOP) { | 
 |   } | 
 |   void SetUp() override { | 
 |     // Start real threads for the IO and File threads so that the DCHECKs | 
 |     // to test that we're on the correct thread work. | 
 |     sb_service_ = new StrictMock<FakeSafeBrowsingService>(); | 
 |     sb_service_->Initialize(); | 
 |     binary_feature_extractor_ = new StrictMock<MockBinaryFeatureExtractor>(); | 
 |     ON_CALL(*binary_feature_extractor_, ExtractImageFeatures(_, _, _, _)) | 
 |         .WillByDefault(Return(true)); | 
 |     download_service_ = sb_service_->download_protection_service(); | 
 |     download_service_->binary_feature_extractor_ = binary_feature_extractor_; | 
 |     download_service_->SetEnabled(true); | 
 |     client_download_request_subscription_ = | 
 |         download_service_->RegisterClientDownloadRequestCallback( | 
 |             base::Bind(&DownloadProtectionServiceTest::OnClientDownloadRequest, | 
 |                        base::Unretained(this))); | 
 |     base::RunLoop().RunUntilIdle(); | 
 |     has_result_ = false; | 
 |  | 
 |     base::FilePath source_path; | 
 |     ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &source_path)); | 
 |     testdata_path_ = source_path | 
 |         .AppendASCII("chrome") | 
 |         .AppendASCII("test") | 
 |         .AppendASCII("data") | 
 |         .AppendASCII("safe_browsing") | 
 |         .AppendASCII("download_protection"); | 
 |  | 
 |     // Setup a profile | 
 |     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); | 
 |     profile_.reset(new TestingProfile(profile_dir_.path())); | 
 |     ASSERT_TRUE(profile_->CreateHistoryService(true /* delete_file */, | 
 |                                                false /* no_db */)); | 
 |   } | 
 |  | 
 |   void TearDown() override { | 
 |     client_download_request_subscription_.reset(); | 
 |     sb_service_->ShutDown(); | 
 |     // Flush all of the thread message loops to ensure that there are no | 
 |     // tasks currently running. | 
 |     FlushThreadMessageLoops(); | 
 |     sb_service_ = NULL; | 
 |   } | 
 |  | 
 |   bool RequestContainsResource(const ClientDownloadRequest& request, | 
 |                                ClientDownloadRequest::ResourceType type, | 
 |                                const std::string& url, | 
 |                                const std::string& referrer) { | 
 |     for (int i = 0; i < request.resources_size(); ++i) { | 
 |       if (request.resources(i).url() == url && | 
 |           request.resources(i).type() == type && | 
 |           (referrer.empty() || request.resources(i).referrer() == referrer)) { | 
 |         return true; | 
 |       } | 
 |     } | 
 |     return false; | 
 |   } | 
 |  | 
 |   // At this point we only set the server IP for the download itself. | 
 |   bool RequestContainsServerIp(const ClientDownloadRequest& request, | 
 |                                const std::string& remote_address) { | 
 |     for (int i = 0; i < request.resources_size(); ++i) { | 
 |       // We want the last DOWNLOAD_URL in the chain. | 
 |       if (request.resources(i).type() == ClientDownloadRequest::DOWNLOAD_URL && | 
 |           (i + 1 == request.resources_size() || | 
 |            request.resources(i + 1).type() != | 
 |            ClientDownloadRequest::DOWNLOAD_URL)) { | 
 |         return remote_address == request.resources(i).remote_ip(); | 
 |       } | 
 |     } | 
 |     return false; | 
 |   } | 
 |  | 
 |   static const ClientDownloadRequest_ArchivedBinary* GetRequestArchivedBinary( | 
 |       const ClientDownloadRequest& request, | 
 |       const std::string& file_basename) { | 
 |     for (const auto& archived_binary : request.archived_binary()) { | 
 |       if (archived_binary.file_basename() == file_basename) | 
 |         return &archived_binary; | 
 |     } | 
 |     return nullptr; | 
 |   } | 
 |  | 
 |   // Flushes any pending tasks in the message loops of all threads. | 
 |   void FlushThreadMessageLoops() { | 
 |     BrowserThread::GetBlockingPool()->FlushForTesting(); | 
 |     FlushMessageLoop(BrowserThread::IO); | 
 |     base::RunLoop().RunUntilIdle(); | 
 |   } | 
 |  | 
 |   // Proxy for private method. | 
 |   static void GetCertificateWhitelistStrings( | 
 |       const net::X509Certificate& certificate, | 
 |       const net::X509Certificate& issuer, | 
 |       std::vector<std::string>* whitelist_strings) { | 
 |     DownloadProtectionService::GetCertificateWhitelistStrings( | 
 |         certificate, issuer, whitelist_strings); | 
 |   } | 
 |  | 
 |   // Reads a single PEM-encoded certificate from the testdata directory. | 
 |   // Returns NULL on failure. | 
 |   scoped_refptr<net::X509Certificate> ReadTestCertificate( | 
 |       const std::string& filename) { | 
 |     std::string cert_data; | 
 |     if (!base::ReadFileToString(testdata_path_.AppendASCII(filename), | 
 |                                 &cert_data)) { | 
 |       return NULL; | 
 |     } | 
 |     net::CertificateList certs = | 
 |         net::X509Certificate::CreateCertificateListFromBytes( | 
 |             cert_data.data(), | 
 |             cert_data.size(), | 
 |             net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE); | 
 |     return certs.empty() ? NULL : certs[0]; | 
 |   } | 
 |  | 
 |   const ClientDownloadRequest* GetClientDownloadRequest() const { | 
 |     return last_client_download_request_.get(); | 
 |   } | 
 |  | 
 |   bool HasClientDownloadRequest() const { | 
 |     return last_client_download_request_.get() != NULL; | 
 |   } | 
 |  | 
 |   void ClearClientDownloadRequest() { last_client_download_request_.reset(); } | 
 |  | 
 |  private: | 
 |   // Helper functions for FlushThreadMessageLoops. | 
 |   void RunAllPendingAndQuitUI() { | 
 |     base::MessageLoop::current()->RunUntilIdle(); | 
 |     BrowserThread::PostTask( | 
 |         BrowserThread::UI, | 
 |         FROM_HERE, | 
 |         base::Bind(&DownloadProtectionServiceTest::QuitMessageLoop, | 
 |                    base::Unretained(this))); | 
 |   } | 
 |  | 
 |   void QuitMessageLoop() { base::MessageLoop::current()->QuitWhenIdle(); } | 
 |  | 
 |   void PostRunMessageLoopTask(BrowserThread::ID thread) { | 
 |     BrowserThread::PostTask( | 
 |         thread, | 
 |         FROM_HERE, | 
 |         base::Bind(&DownloadProtectionServiceTest::RunAllPendingAndQuitUI, | 
 |                    base::Unretained(this))); | 
 |   } | 
 |  | 
 |   void FlushMessageLoop(BrowserThread::ID thread) { | 
 |     BrowserThread::PostTask( | 
 |         BrowserThread::UI, | 
 |         FROM_HERE, | 
 |         base::Bind(&DownloadProtectionServiceTest::PostRunMessageLoopTask, | 
 |                    base::Unretained(this), thread)); | 
 |     MessageLoop::current()->Run(); | 
 |   } | 
 |  | 
 |   void OnClientDownloadRequest(content::DownloadItem* download, | 
 |                                const ClientDownloadRequest* request) { | 
 |     if (request) | 
 |       last_client_download_request_.reset(new ClientDownloadRequest(*request)); | 
 |     else | 
 |       last_client_download_request_.reset(); | 
 |   } | 
 |  | 
 |  public: | 
 |   void CheckDoneCallback( | 
 |       DownloadProtectionService::DownloadCheckResult result) { | 
 |     result_ = result; | 
 |     has_result_ = true; | 
 |     MessageLoop::current()->QuitWhenIdle(); | 
 |   } | 
 |  | 
 |   void SyncCheckDoneCallback( | 
 |       DownloadProtectionService::DownloadCheckResult result) { | 
 |     result_ = result; | 
 |     has_result_ = true; | 
 |   } | 
 |  | 
 |   void SendURLFetchComplete(net::TestURLFetcher* fetcher) { | 
 |     fetcher->delegate()->OnURLFetchComplete(fetcher); | 
 |   } | 
 |  | 
 |   testing::AssertionResult IsResult( | 
 |       DownloadProtectionService::DownloadCheckResult expected) { | 
 |     if (!has_result_) | 
 |       return testing::AssertionFailure() << "No result"; | 
 |     has_result_ = false; | 
 |     return result_ == expected ? | 
 |         testing::AssertionSuccess() : | 
 |         testing::AssertionFailure() << "Expected " << expected << | 
 |                                        ", got " << result_; | 
 |   } | 
 |   // Check scenarios where we should/shouldn't send a report for | 
 |   // a corrupted zip. | 
 |   void CheckClientDownloadReportCorruptZip(bool is_extended_reporting, | 
 |                                            bool is_incognito); | 
 |  | 
 |  | 
 |  protected: | 
 |   scoped_refptr<FakeSafeBrowsingService> sb_service_; | 
 |   scoped_refptr<MockBinaryFeatureExtractor> binary_feature_extractor_; | 
 |   DownloadProtectionService* download_service_; | 
 |   DownloadProtectionService::DownloadCheckResult result_; | 
 |   bool has_result_; | 
 |   content::TestBrowserThreadBundle test_browser_thread_bundle_; | 
 |   content::InProcessUtilityThreadHelper in_process_utility_thread_helper_; | 
 |   base::FilePath testdata_path_; | 
 |   DownloadProtectionService::ClientDownloadRequestSubscription | 
 |       client_download_request_subscription_; | 
 |   scoped_ptr<ClientDownloadRequest> last_client_download_request_; | 
 |   base::ScopedTempDir profile_dir_; | 
 |   scoped_ptr<TestingProfile> profile_; | 
 | }; | 
 |  | 
 |  | 
 | void DownloadProtectionServiceTest::CheckClientDownloadReportCorruptZip( | 
 |     bool is_extended_reporting, | 
 |     bool is_incognito) { | 
 |   ClientDownloadResponse response; | 
 |   response.set_verdict(ClientDownloadResponse::SAFE); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   // Empty response means SAFE. | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   base::ScopedTempDir download_dir; | 
 |   ASSERT_TRUE(download_dir.CreateUniqueTempDir()); | 
 |  | 
 |   base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp"))); | 
 |   base::FilePath a_zip(FILE_PATH_LITERAL("a.zip")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.zip")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |   profile_->GetPrefs()->SetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled, | 
 |                                    is_extended_reporting); | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   if (is_incognito) { | 
 |     EXPECT_CALL(item, GetBrowserContext()) | 
 |         .WillRepeatedly(Return(profile_->GetOffTheRecordProfile())); | 
 |   } else { | 
 |     EXPECT_CALL(item, GetBrowserContext()) | 
 |         .WillRepeatedly(Return(profile_.get())); | 
 |   } | 
 |  | 
 |   std::string file_contents = "corrupt zip file"; | 
 |   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile( | 
 |       a_tmp, file_contents.data(), file_contents.size())); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   const bool expect_request = is_extended_reporting && !is_incognito; | 
 |  | 
 |   if (expect_request) { | 
 |     ASSERT_TRUE(HasClientDownloadRequest()); | 
 |     EXPECT_EQ(0, GetClientDownloadRequest()->archived_binary_size()); | 
 |     EXPECT_TRUE(GetClientDownloadRequest()->has_download_type()); | 
 |     EXPECT_EQ(ClientDownloadRequest_DownloadType_INVALID_ZIP, | 
 |               GetClientDownloadRequest()->download_type()); | 
 |     ClearClientDownloadRequest(); | 
 |   } else { | 
 |     EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |     EXPECT_FALSE(HasClientDownloadRequest()); | 
 |   } | 
 |  | 
 |   Mock::VerifyAndClearExpectations(sb_service_.get()); | 
 |   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get()); | 
 | } | 
 |  | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadInvalidUrl) { | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 |   Mock::VerifyAndClearExpectations(&item); | 
 |  | 
 |   url_chain.push_back(GURL("file://www.google.com/")); | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadNotABinary) { | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_txt(FILE_PATH_LITERAL("a.txt")); | 
 |   std::vector<GURL> url_chain; | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   url_chain.push_back(GURL("http://www.example.com/foo")); | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_txt)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadWhitelistedUrl) { | 
 |   // Response to any requests will be DANGEROUS. | 
 |   ClientDownloadResponse response; | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   std::string hash = "hash"; | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   GURL referrer; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)) | 
 |       .Times(4); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures( | 
 |                   a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)) | 
 |       .Times(4); | 
 |  | 
 |   // We should not get whilelist checks for other URLs than specified below. | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)).Times(0); | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(GURL("http://www.evil.com/bla.exe"))) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(GURL("http://www.google.com/a.exe"))) | 
 |       .WillRepeatedly(Return(true)); | 
 |  | 
 |   // With no referrer and just the bad url, should be marked DANGEROUS. | 
 |   url_chain.push_back(GURL("http://www.evil.com/bla.exe")); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |  | 
 |   // Check that the referrer is not matched against the whitelist. | 
 |   referrer = GURL("http://www.google.com/"); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |  | 
 |   // Redirect from a site shouldn't be checked either. | 
 |   url_chain.insert(url_chain.begin(), GURL("http://www.google.com/redirect")); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |  | 
 |   // Only if the final url is whitelisted should it be SAFE. | 
 |   url_chain.push_back(GURL("http://www.google.com/a.exe")); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE)); | 
 |   // TODO(grt): Make the service produce the request even when the URL is | 
 |   // whitelisted. | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadFetchFailed) { | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   // HTTP request will fail. | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), std::string(), | 
 |       net::HTTP_INTERNAL_SERVER_ERROR, net::URLRequestStatus::FAILED); | 
 |  | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)); | 
 |   EXPECT_CALL( | 
 |       *binary_feature_extractor_.get(), | 
 |       ExtractImageFeatures(a_tmp, BinaryFeatureExtractor::kDefaultOptions, | 
 |                            _, _)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadSuccess) { | 
 |   ClientDownloadResponse response; | 
 |   response.set_verdict(ClientDownloadResponse::SAFE); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   // Empty response means SAFE. | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)) | 
 |       .Times(6); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures( | 
 |                   a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)) | 
 |       .Times(6); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |  | 
 |   // Invalid response should result in UNKNOWN. | 
 |   response.Clear(); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializePartialAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |   std::string feedback_ping; | 
 |   std::string feedback_response; | 
 |   EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting( | 
 |       item, &feedback_ping, &feedback_response)); | 
 |  | 
 |   // If the response is dangerous the result should also be marked as dangerous. | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting( | 
 |       item, &feedback_ping, &feedback_response)); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |  | 
 |   // If the response is uncommon the result should also be marked as uncommon. | 
 |   response.set_verdict(ClientDownloadResponse::UNCOMMON); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNCOMMON)); | 
 |   EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting( | 
 |       item, &feedback_ping, &feedback_response)); | 
 |   ClientDownloadRequest decoded_request; | 
 |   EXPECT_TRUE(decoded_request.ParseFromString(feedback_ping)); | 
 |   EXPECT_EQ(url_chain.back().spec(), decoded_request.url()); | 
 |   EXPECT_EQ(response.SerializeAsString(), feedback_response); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |  | 
 |   // If the response is dangerous_host the result should also be marked as | 
 |   // dangerous_host. | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS_HOST); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS_HOST)); | 
 |   EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting( | 
 |       item, &feedback_ping, &feedback_response)); | 
 |   EXPECT_EQ(response.SerializeAsString(), feedback_response); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |  | 
 |   // If the response is POTENTIALLY_UNWANTED the result should also be marked as | 
 |   // POTENTIALLY_UNWANTED. | 
 |   response.set_verdict(ClientDownloadResponse::POTENTIALLY_UNWANTED); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::POTENTIALLY_UNWANTED)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadHTTPS) { | 
 |   ClientDownloadResponse response; | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)) | 
 |       .Times(1); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures( | 
 |                   a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)) | 
 |       .Times(1); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadBlob) { | 
 |   ClientDownloadResponse response; | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   factory.SetFakeResponse(DownloadProtectionService::GetDownloadRequestUrl(), | 
 |                           response.SerializeAsString(), net::HTTP_OK, | 
 |                           net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back( | 
 |       GURL("blob:http://www.evil.com/50b85f60-71e4-11e4-82f8-0800200c9a66")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)).WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)) | 
 |       .Times(1); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures( | 
 |                   a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)) | 
 |       .Times(1); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadData) { | 
 |   ClientDownloadResponse response; | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   factory.SetFakeResponse(DownloadProtectionService::GetDownloadRequestUrl(), | 
 |                           response.SerializeAsString(), net::HTTP_OK, | 
 |                           net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back( | 
 |       GURL("data:text/html:base64,")); | 
 |   url_chain.push_back( | 
 |       GURL("data:text/html:base64,blahblahblah")); | 
 |   url_chain.push_back( | 
 |       GURL("data:application/octet-stream:base64,blahblah")); | 
 |   GURL referrer("data:text/html:base64,foobar"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)).WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)) | 
 |       .Times(1); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures( | 
 |                   a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)) | 
 |       .Times(1); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   ASSERT_TRUE(HasClientDownloadRequest()); | 
 |   const ClientDownloadRequest& request = *GetClientDownloadRequest(); | 
 |   const char kExpectedUrl[] = | 
 |       "data:application/octet-stream:base64," | 
 |       "ACBF6DFC6F907662F566CA0241DFE8690C48661F440BA1BBD0B86C582845CCC8"; | 
 |   const char kExpectedRedirect1[] = "data:text/html:base64,"; | 
 |   const char kExpectedRedirect2[] = | 
 |       "data:text/html:base64," | 
 |       "620680767E15717A57DB11D94D1BEBD32B3344EBC5994DF4FB07B0D473F4EF6B"; | 
 |   const char kExpectedReferrer[] = | 
 |       "data:text/html:base64," | 
 |       "06E2C655B9F7130B508FFF86FD19B57E6BF1A1CFEFD6EFE1C3EB09FE24EF456A"; | 
 |   EXPECT_EQ(hash, request.digests().sha256()); | 
 |   EXPECT_EQ(kExpectedUrl, request.url()); | 
 |   EXPECT_EQ(3, request.resources_size()); | 
 |   EXPECT_TRUE(RequestContainsResource(request, | 
 |                                       ClientDownloadRequest::DOWNLOAD_REDIRECT, | 
 |                                       kExpectedRedirect1, "")); | 
 |   EXPECT_TRUE(RequestContainsResource(request, | 
 |                                       ClientDownloadRequest::DOWNLOAD_REDIRECT, | 
 |                                       kExpectedRedirect2, "")); | 
 |   EXPECT_TRUE(RequestContainsResource(request, | 
 |                                       ClientDownloadRequest::DOWNLOAD_URL, | 
 |                                       kExpectedUrl, kExpectedReferrer)); | 
 |   ClearClientDownloadRequest(); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadZip) { | 
 |   ClientDownloadResponse response; | 
 |   response.set_verdict(ClientDownloadResponse::SAFE); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   // Empty response means SAFE. | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   base::ScopedTempDir download_dir; | 
 |   ASSERT_TRUE(download_dir.CreateUniqueTempDir()); | 
 |  | 
 |   base::FilePath a_tmp(download_dir.path().Append(FILE_PATH_LITERAL("a.tmp"))); | 
 |   base::FilePath a_zip(FILE_PATH_LITERAL("a.zip")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.zip")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   // Write out a zip archive to the temporary file.  In this case, it | 
 |   // only contains a text file. | 
 |   base::ScopedTempDir zip_source_dir; | 
 |   ASSERT_TRUE(zip_source_dir.CreateUniqueTempDir()); | 
 |   std::string file_contents = "dummy file"; | 
 |   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile( | 
 |       zip_source_dir.path().Append(FILE_PATH_LITERAL("file.txt")), | 
 |       file_contents.data(), file_contents.size())); | 
 |   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 |   Mock::VerifyAndClearExpectations(sb_service_.get()); | 
 |   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get()); | 
 |  | 
 |   // Now check with an executable in the zip file as well. | 
 |   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile( | 
 |       zip_source_dir.path().Append(FILE_PATH_LITERAL("file.exe")), | 
 |       file_contents.data(), file_contents.size())); | 
 |   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false)); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   const ClientDownloadRequest& request = *GetClientDownloadRequest(); | 
 |   EXPECT_TRUE(request.has_download_type()); | 
 |   EXPECT_EQ(ClientDownloadRequest_DownloadType_ZIPPED_EXECUTABLE, | 
 |             request.download_type()); | 
 |   EXPECT_EQ(1, request.archived_binary_size()); | 
 |   const ClientDownloadRequest_ArchivedBinary* archived_binary = | 
 |       GetRequestArchivedBinary(request, "file.exe"); | 
 |   ASSERT_NE(nullptr, archived_binary); | 
 |   EXPECT_EQ(ClientDownloadRequest_DownloadType_WIN_EXECUTABLE, | 
 |             archived_binary->download_type()); | 
 |   EXPECT_EQ(static_cast<int64_t>(file_contents.size()), | 
 |             archived_binary->length()); | 
 |   ClearClientDownloadRequest(); | 
 |   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get()); | 
 |  | 
 |   // If the response is dangerous the result should also be marked as | 
 |   // dangerous. | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS); | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get()); | 
 |  | 
 |   // Repeat the test with an archive inside the zip file in addition to the | 
 |   // executable. | 
 |   ASSERT_EQ(static_cast<int>(file_contents.size()), | 
 |             base::WriteFile( | 
 |                 zip_source_dir.path().Append(FILE_PATH_LITERAL("file.rar")), | 
 |                 file_contents.data(), file_contents.size())); | 
 |   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                         base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   ASSERT_TRUE(HasClientDownloadRequest()); | 
 |   EXPECT_EQ(1, GetClientDownloadRequest()->archived_binary_size()); | 
 |   EXPECT_TRUE(GetClientDownloadRequest()->has_download_type()); | 
 |   EXPECT_EQ(ClientDownloadRequest_DownloadType_ZIPPED_EXECUTABLE, | 
 |             GetClientDownloadRequest()->download_type()); | 
 |   ClearClientDownloadRequest(); | 
 |   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get()); | 
 |  | 
 |   // Repeat the test with just the archive inside the zip file. | 
 |   ASSERT_TRUE( | 
 |       base::DeleteFile(zip_source_dir.path().AppendASCII("file.exe"), false)); | 
 |   ASSERT_TRUE(zip::Zip(zip_source_dir.path(), a_tmp, false)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                         base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   ASSERT_TRUE(HasClientDownloadRequest()); | 
 |   EXPECT_EQ(0, GetClientDownloadRequest()->archived_binary_size()); | 
 |   EXPECT_TRUE(GetClientDownloadRequest()->has_download_type()); | 
 |   EXPECT_EQ(ClientDownloadRequest_DownloadType_ZIPPED_ARCHIVE, | 
 |             GetClientDownloadRequest()->download_type()); | 
 |   ClearClientDownloadRequest(); | 
 |   Mock::VerifyAndClearExpectations(binary_feature_extractor_.get()); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, | 
 |        CheckClientDownloadReportCorruptZipNormal) { | 
 |   // !is_extended_reporting && !is_incognito | 
 |   CheckClientDownloadReportCorruptZip(false, false); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, | 
 |        CheckClientDownloadReportCorruptZipExtended) { | 
 |   // !is_extended_reporting && !is_incognito | 
 |   CheckClientDownloadReportCorruptZip(true, false); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, | 
 |        CheckClientDownloadReportCorruptZipIncognito) { | 
 |   // is_extended_reporting && is_incognito | 
 |   CheckClientDownloadReportCorruptZip(true, true); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientCrxDownloadSuccess) { | 
 |   ClientDownloadResponse response; | 
 |   // Even if the server verdict is dangerous we should return SAFE because | 
 |   // DownloadProtectionService::IsSupportedDownload() will return false | 
 |   // for crx downloads. | 
 |   response.set_verdict(ClientDownloadResponse::DANGEROUS); | 
 |   net::FakeURLFetcherFactory factory(NULL); | 
 |   // Empty response means SAFE. | 
 |   factory.SetFakeResponse( | 
 |       DownloadProtectionService::GetDownloadRequestUrl(), | 
 |       response.SerializeAsString(), | 
 |       net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 
 |  | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_crx(FILE_PATH_LITERAL("a.crx")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.crx")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_crx)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)) | 
 |       .Times(1); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures( | 
 |                   a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)) | 
 |               .Times(1); | 
 |  | 
 |   EXPECT_FALSE(download_service_->IsSupportedDownload(item, a_crx)); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, CheckClientDownloadValidateRequest) { | 
 |   net::TestURLFetcherFactory factory; | 
 |  | 
 |   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp")); | 
 |   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.google.com/")); | 
 |   url_chain.push_back(GURL("http://www.google.com/bla.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |   std::string remote_address = "10.11.12.13"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address)); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _)) | 
 |       .WillOnce(SetCertificateContents("dummy cert data")); | 
 |   EXPECT_CALL( | 
 |       *binary_feature_extractor_.get(), | 
 |       ExtractImageFeatures(tmp_path, BinaryFeatureExtractor::kDefaultOptions, | 
 |                            _, _)) | 
 |       .WillOnce(SetDosHeaderContents("dummy dos header")); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |  | 
 |   // Run the message loop(s) until SendRequest is called. | 
 |   FlushThreadMessageLoops(); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); | 
 |   ASSERT_TRUE(fetcher); | 
 |   ClientDownloadRequest request; | 
 |   EXPECT_TRUE(request.ParseFromString(fetcher->upload_data())); | 
 |   EXPECT_EQ("http://www.google.com/bla.exe", request.url()); | 
 |   EXPECT_EQ(hash, request.digests().sha256()); | 
 |   EXPECT_EQ(item.GetReceivedBytes(), request.length()); | 
 |   EXPECT_EQ(item.HasUserGesture(), request.user_initiated()); | 
 |   EXPECT_TRUE(RequestContainsServerIp(request, remote_address)); | 
 |   EXPECT_EQ(2, request.resources_size()); | 
 |   EXPECT_TRUE(RequestContainsResource(request, | 
 |                                       ClientDownloadRequest::DOWNLOAD_REDIRECT, | 
 |                                       "http://www.google.com/", "")); | 
 |   EXPECT_TRUE(RequestContainsResource(request, | 
 |                                       ClientDownloadRequest::DOWNLOAD_URL, | 
 |                                       "http://www.google.com/bla.exe", | 
 |                                       referrer.spec())); | 
 |   EXPECT_TRUE(request.has_signature()); | 
 |   ASSERT_EQ(1, request.signature().certificate_chain_size()); | 
 |   const ClientDownloadRequest_CertificateChain& chain = | 
 |       request.signature().certificate_chain(0); | 
 |   ASSERT_EQ(1, chain.element_size()); | 
 |   EXPECT_EQ("dummy cert data", chain.element(0).certificate()); | 
 |   EXPECT_TRUE(request.has_image_headers()); | 
 |   const ClientDownloadRequest_ImageHeaders& headers = | 
 |       request.image_headers(); | 
 |   EXPECT_TRUE(headers.has_pe_headers()); | 
 |   EXPECT_TRUE(headers.pe_headers().has_dos_header()); | 
 |   EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header()); | 
 |  | 
 |   // Simulate the request finishing. | 
 |   base::MessageLoop::current()->PostTask( | 
 |       FROM_HERE, | 
 |       base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete, | 
 |                  base::Unretained(this), fetcher)); | 
 |   MessageLoop::current()->Run(); | 
 | } | 
 |  | 
 | // Similar to above, but with an unsigned binary. | 
 | TEST_F(DownloadProtectionServiceTest, | 
 |        CheckClientDownloadValidateRequestNoSignature) { | 
 |   net::TestURLFetcherFactory factory; | 
 |  | 
 |   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp")); | 
 |   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.google.com/")); | 
 |   url_chain.push_back(GURL("ftp://www.google.com/bla.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |   std::string remote_address = "10.11.12.13"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address)); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures(tmp_path, | 
 |                                    BinaryFeatureExtractor::kDefaultOptions, | 
 |                                    _, _)); | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |  | 
 |   // Run the message loop(s) until SendRequest is called. | 
 |   FlushThreadMessageLoops(); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 |   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); | 
 |   ASSERT_TRUE(fetcher); | 
 |   ClientDownloadRequest request; | 
 |   EXPECT_TRUE(request.ParseFromString(fetcher->upload_data())); | 
 |   EXPECT_EQ("ftp://www.google.com/bla.exe", request.url()); | 
 |   EXPECT_EQ(hash, request.digests().sha256()); | 
 |   EXPECT_EQ(item.GetReceivedBytes(), request.length()); | 
 |   EXPECT_EQ(item.HasUserGesture(), request.user_initiated()); | 
 |   EXPECT_EQ(2, request.resources_size()); | 
 |   EXPECT_TRUE(RequestContainsResource(request, | 
 |                                       ClientDownloadRequest::DOWNLOAD_REDIRECT, | 
 |                                       "http://www.google.com/", "")); | 
 |   EXPECT_TRUE(RequestContainsResource(request, | 
 |                                       ClientDownloadRequest::DOWNLOAD_URL, | 
 |                                       "ftp://www.google.com/bla.exe", | 
 |                                       referrer.spec())); | 
 |   EXPECT_TRUE(request.has_signature()); | 
 |   EXPECT_EQ(0, request.signature().certificate_chain_size()); | 
 |  | 
 |   // Simulate the request finishing. | 
 |   base::MessageLoop::current()->PostTask( | 
 |       FROM_HERE, | 
 |       base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete, | 
 |                  base::Unretained(this), fetcher)); | 
 |   MessageLoop::current()->Run(); | 
 | } | 
 |  | 
 | // Similar to above, but with tab history. | 
 | TEST_F(DownloadProtectionServiceTest, | 
 |        CheckClientDownloadValidateRequestTabHistory) { | 
 |   net::TestURLFetcherFactory factory; | 
 |  | 
 |   base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp")); | 
 |   base::FilePath final_path(FILE_PATH_LITERAL("bla.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.google.com/")); | 
 |   url_chain.push_back(GURL("http://www.google.com/bla.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   GURL tab_url("http://tab.com/final"); | 
 |   GURL tab_referrer("http://tab.com/referrer"); | 
 |   std::string hash = "hash"; | 
 |   std::string remote_address = "10.11.12.13"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url)); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(tab_referrer)); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address)); | 
 |   EXPECT_CALL(item, GetBrowserContext()).WillRepeatedly(Return(profile_.get())); | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _)) | 
 |       .WillRepeatedly(SetCertificateContents("dummy cert data")); | 
 |   EXPECT_CALL( | 
 |       *binary_feature_extractor_.get(), | 
 |       ExtractImageFeatures(tmp_path, BinaryFeatureExtractor::kDefaultOptions, | 
 |                            _, _)) | 
 |       .WillRepeatedly(SetDosHeaderContents("dummy dos header")); | 
 |  | 
 |   // First test with no history match for the tab URL. | 
 |   { | 
 |     TestURLFetcherWatcher fetcher_watcher(&factory); | 
 |     download_service_->CheckClientDownload( | 
 |         &item, | 
 |         base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                    base::Unretained(this))); | 
 |  | 
 |     EXPECT_EQ(0, fetcher_watcher.WaitForRequest()); | 
 |     EXPECT_TRUE(HasClientDownloadRequest()); | 
 |     ClearClientDownloadRequest(); | 
 |     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); | 
 |     ASSERT_TRUE(fetcher); | 
 |     ClientDownloadRequest request; | 
 |     EXPECT_TRUE(request.ParseFromString(fetcher->upload_data())); | 
 |     EXPECT_EQ("http://www.google.com/bla.exe", request.url()); | 
 |     EXPECT_EQ(hash, request.digests().sha256()); | 
 |     EXPECT_EQ(item.GetReceivedBytes(), request.length()); | 
 |     EXPECT_EQ(item.HasUserGesture(), request.user_initiated()); | 
 |     EXPECT_TRUE(RequestContainsServerIp(request, remote_address)); | 
 |     EXPECT_EQ(3, request.resources_size()); | 
 |     EXPECT_TRUE( | 
 |         RequestContainsResource(request, | 
 |                                 ClientDownloadRequest::DOWNLOAD_REDIRECT, | 
 |                                 "http://www.google.com/", | 
 |                                 "")); | 
 |     EXPECT_TRUE(RequestContainsResource(request, | 
 |                                         ClientDownloadRequest::DOWNLOAD_URL, | 
 |                                         "http://www.google.com/bla.exe", | 
 |                                         referrer.spec())); | 
 |     EXPECT_TRUE(RequestContainsResource(request, | 
 |                                         ClientDownloadRequest::TAB_URL, | 
 |                                         tab_url.spec(), | 
 |                                         tab_referrer.spec())); | 
 |     EXPECT_TRUE(request.has_signature()); | 
 |     ASSERT_EQ(1, request.signature().certificate_chain_size()); | 
 |     const ClientDownloadRequest_CertificateChain& chain = | 
 |         request.signature().certificate_chain(0); | 
 |     ASSERT_EQ(1, chain.element_size()); | 
 |     EXPECT_EQ("dummy cert data", chain.element(0).certificate()); | 
 |     EXPECT_TRUE(request.has_image_headers()); | 
 |     const ClientDownloadRequest_ImageHeaders& headers = | 
 |         request.image_headers(); | 
 |     EXPECT_TRUE(headers.has_pe_headers()); | 
 |     EXPECT_TRUE(headers.pe_headers().has_dos_header()); | 
 |     EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header()); | 
 |  | 
 |     // Simulate the request finishing. | 
 |     base::MessageLoop::current()->PostTask( | 
 |         FROM_HERE, | 
 |         base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete, | 
 |                    base::Unretained(this), | 
 |                    fetcher)); | 
 |     MessageLoop::current()->Run(); | 
 |   } | 
 |  | 
 |   // Now try with a history match. | 
 |   { | 
 |     history::RedirectList redirects; | 
 |     redirects.push_back(GURL("http://tab.com/ref1")); | 
 |     redirects.push_back(GURL("http://tab.com/ref2")); | 
 |     redirects.push_back(tab_url); | 
 |     HistoryServiceFactory::GetForProfile(profile_.get(), | 
 |                                          ServiceAccessType::EXPLICIT_ACCESS) | 
 |         ->AddPage(tab_url, | 
 |                   base::Time::Now(), | 
 |                   reinterpret_cast<history::ContextID>(1), | 
 |                   0, | 
 |                   GURL(), | 
 |                   redirects, | 
 |                   ui::PAGE_TRANSITION_TYPED, | 
 |                   history::SOURCE_BROWSED, | 
 |                   false); | 
 |  | 
 |     TestURLFetcherWatcher fetcher_watcher(&factory); | 
 |     download_service_->CheckClientDownload( | 
 |         &item, | 
 |         base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                    base::Unretained(this))); | 
 |     EXPECT_EQ(0, fetcher_watcher.WaitForRequest()); | 
 |     EXPECT_TRUE(HasClientDownloadRequest()); | 
 |     ClearClientDownloadRequest(); | 
 |     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); | 
 |     ASSERT_TRUE(fetcher); | 
 |     ClientDownloadRequest request; | 
 |     EXPECT_TRUE(request.ParseFromString(fetcher->upload_data())); | 
 |     EXPECT_EQ("http://www.google.com/bla.exe", request.url()); | 
 |     EXPECT_EQ(hash, request.digests().sha256()); | 
 |     EXPECT_EQ(item.GetReceivedBytes(), request.length()); | 
 |     EXPECT_EQ(item.HasUserGesture(), request.user_initiated()); | 
 |     EXPECT_TRUE(RequestContainsServerIp(request, remote_address)); | 
 |     EXPECT_EQ(5, request.resources_size()); | 
 |     EXPECT_TRUE( | 
 |         RequestContainsResource(request, | 
 |                                 ClientDownloadRequest::DOWNLOAD_REDIRECT, | 
 |                                 "http://www.google.com/", | 
 |                                 "")); | 
 |     EXPECT_TRUE(RequestContainsResource(request, | 
 |                                         ClientDownloadRequest::DOWNLOAD_URL, | 
 |                                         "http://www.google.com/bla.exe", | 
 |                                         referrer.spec())); | 
 |     EXPECT_TRUE(RequestContainsResource(request, | 
 |                                         ClientDownloadRequest::TAB_REDIRECT, | 
 |                                         "http://tab.com/ref1", | 
 |                                         "")); | 
 |     EXPECT_TRUE(RequestContainsResource(request, | 
 |                                         ClientDownloadRequest::TAB_REDIRECT, | 
 |                                         "http://tab.com/ref2", | 
 |                                         "")); | 
 |     EXPECT_TRUE(RequestContainsResource(request, | 
 |                                         ClientDownloadRequest::TAB_URL, | 
 |                                         tab_url.spec(), | 
 |                                         tab_referrer.spec())); | 
 |     EXPECT_TRUE(request.has_signature()); | 
 |     ASSERT_EQ(1, request.signature().certificate_chain_size()); | 
 |     const ClientDownloadRequest_CertificateChain& chain = | 
 |         request.signature().certificate_chain(0); | 
 |     ASSERT_EQ(1, chain.element_size()); | 
 |     EXPECT_EQ("dummy cert data", chain.element(0).certificate()); | 
 |  | 
 |     // Simulate the request finishing. | 
 |     base::MessageLoop::current()->PostTask( | 
 |         FROM_HERE, | 
 |         base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete, | 
 |                    base::Unretained(this), | 
 |                    fetcher)); | 
 |     MessageLoop::current()->Run(); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, TestCheckDownloadUrl) { | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.google.com/")); | 
 |   url_chain.push_back(GURL("http://www.google.com/bla.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |  | 
 |   // CheckDownloadURL returns immediately which means the client object callback | 
 |   // will never be called.  Nevertheless the callback provided to | 
 |   // CheckClientDownload must still be called. | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               CheckDownloadUrl(ContainerEq(url_chain), NotNull())) | 
 |       .WillOnce(Return(true)); | 
 |   download_service_->CheckDownloadUrl( | 
 |       item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE)); | 
 |   Mock::VerifyAndClearExpectations(sb_service_.get()); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               CheckDownloadUrl(ContainerEq(url_chain), NotNull())) | 
 |       .WillOnce(DoAll(CheckDownloadUrlDone(SB_THREAT_TYPE_SAFE), | 
 |                       Return(false))); | 
 |   download_service_->CheckDownloadUrl( | 
 |       item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE)); | 
 |   Mock::VerifyAndClearExpectations(sb_service_.get()); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               CheckDownloadUrl(ContainerEq(url_chain), NotNull())) | 
 |       .WillOnce(DoAll( | 
 |           CheckDownloadUrlDone(SB_THREAT_TYPE_URL_MALWARE), | 
 |           Return(false))); | 
 |   download_service_->CheckDownloadUrl( | 
 |       item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE)); | 
 |   Mock::VerifyAndClearExpectations(sb_service_.get()); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               CheckDownloadUrl(ContainerEq(url_chain), | 
 |                                NotNull())) | 
 |       .WillOnce(DoAll( | 
 |           CheckDownloadUrlDone(SB_THREAT_TYPE_BINARY_MALWARE_URL), | 
 |           Return(false))); | 
 |   download_service_->CheckDownloadUrl( | 
 |       item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, TestDownloadRequestTimeout) { | 
 |   net::TestURLFetcherFactory factory; | 
 |  | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/bla.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath final_path(FILE_PATH_LITERAL("a.exe")); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures(tmp_path, | 
 |                                    BinaryFeatureExtractor::kDefaultOptions, | 
 |                                    _, _)); | 
 |  | 
 |   download_service_->download_request_timeout_ms_ = 10; | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |  | 
 |   // The request should time out because the HTTP request hasn't returned | 
 |   // anything yet. | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_TRUE(HasClientDownloadRequest()); | 
 |   ClearClientDownloadRequest(); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, TestDownloadItemDestroyed) { | 
 |   net::TestURLFetcherFactory factory; | 
 |  | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/bla.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   GURL tab_url("http://www.google.com/tab"); | 
 |   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath final_path(FILE_PATH_LITERAL("a.exe")); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   { | 
 |     content::MockDownloadItem item; | 
 |     EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path)); | 
 |     EXPECT_CALL(item, GetTargetFilePath()) | 
 |         .WillRepeatedly(ReturnRef(final_path)); | 
 |     EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |     EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |     EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url)); | 
 |     EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |         .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |     EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |     EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |     EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |     EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |     EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |                 MatchDownloadWhitelistUrl(_)) | 
 |         .WillRepeatedly(Return(false)); | 
 |     EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _)); | 
 |     EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |                 ExtractImageFeatures( | 
 |                     tmp_path, BinaryFeatureExtractor::kDefaultOptions, _, _)); | 
 |  | 
 |     download_service_->CheckClientDownload( | 
 |         &item, | 
 |         base::Bind(&DownloadProtectionServiceTest::SyncCheckDoneCallback, | 
 |                    base::Unretained(this))); | 
 |     // MockDownloadItem going out of scope triggers the OnDownloadDestroyed | 
 |     // notification. | 
 |   } | 
 |  | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, | 
 |        TestDownloadItemDestroyedDuringWhitelistCheck) { | 
 |   net::TestURLFetcherFactory factory; | 
 |  | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/bla.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   GURL tab_url("http://www.google.com/tab"); | 
 |   base::FilePath tmp_path(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath final_path(FILE_PATH_LITERAL("a.exe")); | 
 |   std::string hash = "hash"; | 
 |  | 
 |   scoped_ptr<content::MockDownloadItem> item(new content::MockDownloadItem); | 
 |   EXPECT_CALL(*item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path)); | 
 |   EXPECT_CALL(*item, GetTargetFilePath()) | 
 |       .WillRepeatedly(ReturnRef(final_path)); | 
 |   EXPECT_CALL(*item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(*item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(*item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url)); | 
 |   EXPECT_CALL(*item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(*item, GetHash()).WillRepeatedly(ReturnRef(hash)); | 
 |   EXPECT_CALL(*item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(*item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(*item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Invoke([&item](const GURL&) { | 
 |         item.reset(); | 
 |         return false; | 
 |       })); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures(tmp_path, | 
 |                                    BinaryFeatureExtractor::kDefaultOptions, | 
 |                                    _, _)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       item.get(), | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |  | 
 |   MessageLoop::current()->Run(); | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN)); | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 | } | 
 |  | 
 | TEST_F(DownloadProtectionServiceTest, GetCertificateWhitelistStrings) { | 
 |   // We'll pass this cert in as the "issuer", even though it isn't really | 
 |   // used to sign the certs below.  GetCertificateWhitelistStirngs doesn't care | 
 |   // about this. | 
 |   scoped_refptr<net::X509Certificate> issuer_cert( | 
 |       ReadTestCertificate("issuer.pem")); | 
 |   ASSERT_TRUE(issuer_cert.get()); | 
 |   std::string cert_base = "cert/" + base::HexEncode( | 
 |       issuer_cert->fingerprint().data, | 
 |       sizeof(issuer_cert->fingerprint().data)); | 
 |  | 
 |   scoped_refptr<net::X509Certificate> cert(ReadTestCertificate("test_cn.pem")); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   std::vector<std::string> whitelist_strings; | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   // This also tests escaping of characters in the certificate attributes. | 
 |   EXPECT_THAT(whitelist_strings, ElementsAre( | 
 |       cert_base + "/CN=subject%2F%251")); | 
 |  | 
 |   cert = ReadTestCertificate("test_cn_o.pem"); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   whitelist_strings.clear(); | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   EXPECT_THAT(whitelist_strings, | 
 |               ElementsAre(cert_base + "/CN=subject", | 
 |                           cert_base + "/CN=subject/O=org", | 
 |                           cert_base + "/O=org")); | 
 |  | 
 |   cert = ReadTestCertificate("test_cn_o_ou.pem"); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   whitelist_strings.clear(); | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   EXPECT_THAT(whitelist_strings, | 
 |               ElementsAre(cert_base + "/CN=subject", | 
 |                           cert_base + "/CN=subject/O=org", | 
 |                           cert_base + "/CN=subject/O=org/OU=unit", | 
 |                           cert_base + "/CN=subject/OU=unit", | 
 |                           cert_base + "/O=org", | 
 |                           cert_base + "/O=org/OU=unit", | 
 |                           cert_base + "/OU=unit")); | 
 |  | 
 |   cert = ReadTestCertificate("test_cn_ou.pem"); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   whitelist_strings.clear(); | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   EXPECT_THAT(whitelist_strings, | 
 |               ElementsAre(cert_base + "/CN=subject", | 
 |                           cert_base + "/CN=subject/OU=unit", | 
 |                           cert_base + "/OU=unit")); | 
 |  | 
 |   cert = ReadTestCertificate("test_o.pem"); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   whitelist_strings.clear(); | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/O=org")); | 
 |  | 
 |   cert = ReadTestCertificate("test_o_ou.pem"); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   whitelist_strings.clear(); | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   EXPECT_THAT(whitelist_strings, | 
 |               ElementsAre(cert_base + "/O=org", | 
 |                           cert_base + "/O=org/OU=unit", | 
 |                           cert_base + "/OU=unit")); | 
 |  | 
 |   cert = ReadTestCertificate("test_ou.pem"); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   whitelist_strings.clear(); | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/OU=unit")); | 
 |  | 
 |   cert = ReadTestCertificate("test_c.pem"); | 
 |   ASSERT_TRUE(cert.get()); | 
 |   whitelist_strings.clear(); | 
 |   GetCertificateWhitelistStrings( | 
 |       *cert.get(), *issuer_cert.get(), &whitelist_strings); | 
 |   EXPECT_THAT(whitelist_strings, ElementsAre()); | 
 | } | 
 |  | 
 | namespace { | 
 |  | 
 | class MockPageNavigator : public content::PageNavigator { | 
 |  public: | 
 |   MOCK_METHOD1(OpenURL, content::WebContents*(const content::OpenURLParams&)); | 
 | }; | 
 |  | 
 | // A custom matcher that matches a OpenURLParams value with a url with a query | 
 | // parameter patching |value|. | 
 | MATCHER_P(OpenURLParamsWithContextValue, value, "") { | 
 |   std::string query_value; | 
 |   return net::GetValueForKeyInQuery(arg.url, "ctx", &query_value) && | 
 |          query_value == value; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | // ShowDetailsForDownload() should open a URL showing more information about why | 
 | // a download was flagged by SafeBrowsing. The URL should have a &ctx= parameter | 
 | // whose value is the DownloadDangerType. | 
 | TEST_F(DownloadProtectionServiceTest, ShowDetailsForDownloadHasContext) { | 
 |   StrictMock<MockPageNavigator> mock_page_navigator; | 
 |   StrictMock<content::MockDownloadItem> mock_download_item; | 
 |  | 
 |   EXPECT_CALL(mock_download_item, GetDangerType()) | 
 |       .WillOnce(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST)); | 
 |   EXPECT_CALL(mock_page_navigator, OpenURL(OpenURLParamsWithContextValue("7"))); | 
 |  | 
 |   download_service_->ShowDetailsForDownload(mock_download_item, | 
 |                                             &mock_page_navigator); | 
 | } | 
 |  | 
 | // ------------ class DownloadProtectionServiceFlagTest ---------------- | 
 | class DownloadProtectionServiceFlagTest : public DownloadProtectionServiceTest { | 
 |  protected: | 
 |   DownloadProtectionServiceFlagTest() | 
 |       // Matches unsigned.exe within zipfile_one_unsigned_binary.zip | 
 |       : blacklisted_hash_hex_("1e954d9ce0389e2ba7447216f21761f98d1e6540c2abecdbecff570e36c493db") {} | 
 |  | 
 |   void SetUp() override { | 
 |     std::vector<uint8_t> bytes; | 
 |     ASSERT_TRUE(base::HexStringToBytes(blacklisted_hash_hex_, &bytes) && | 
 |                 bytes.size() == 32); | 
 |     blacklisted_hash_ = std::string(bytes.begin(), bytes.end()); | 
 |  | 
 |     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( | 
 |         switches::kSbManualDownloadBlacklist, | 
 |         blacklisted_hash_hex_); | 
 |  | 
 |     DownloadProtectionServiceTest::SetUp(); | 
 |   } | 
 |  | 
 |   // Hex 64 chars | 
 |   const std::string blacklisted_hash_hex_; | 
 |   // Binary 32 bytes | 
 |   std::string blacklisted_hash_; | 
 | }; | 
 |  | 
 | TEST_F(DownloadProtectionServiceFlagTest, CheckClientDownloadOverridenByFlag) { | 
 |   base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp")); | 
 |   base::FilePath a_exe(FILE_PATH_LITERAL("a.exe")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.exe")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(blacklisted_hash_)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _)); | 
 |   EXPECT_CALL(*binary_feature_extractor_.get(), | 
 |               ExtractImageFeatures( | 
 |                   a_tmp, BinaryFeatureExtractor::kDefaultOptions, _, _)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, | 
 |       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                  base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 |   // Overriden by flag: | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 | } | 
 |  | 
 | // Test a real .zip with a real .exe in it, where the .exe is manually | 
 | // blacklisted by hash. | 
 | TEST_F(DownloadProtectionServiceFlagTest, | 
 |        CheckClientDownloadZipOverridenByFlag) { | 
 |   const base::FilePath zip_path = | 
 |       testdata_path_.AppendASCII("zipfile_one_unsigned_binary.zip"); | 
 |  | 
 |   base::FilePath final_path(FILE_PATH_LITERAL("a.zip")); | 
 |   std::vector<GURL> url_chain; | 
 |   url_chain.push_back(GURL("http://www.evil.com/a.zip")); | 
 |   GURL referrer("http://www.google.com/"); | 
 |   std::string zip_hash("hash");  // not blacklisted | 
 |  | 
 |   content::MockDownloadItem item; | 
 |   EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(zip_path)); | 
 |   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path)); | 
 |   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain)); | 
 |   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer)); | 
 |   EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetTabReferrerUrl()) | 
 |       .WillRepeatedly(ReturnRef(GURL::EmptyGURL())); | 
 |   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(zip_hash)); | 
 |   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100)); | 
 |   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true)); | 
 |   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return("")); | 
 |  | 
 |   EXPECT_CALL(*sb_service_->mock_database_manager(), | 
 |               MatchDownloadWhitelistUrl(_)) | 
 |       .WillRepeatedly(Return(false)); | 
 |  | 
 |   download_service_->CheckClientDownload( | 
 |       &item, base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 
 |                         base::Unretained(this))); | 
 |   MessageLoop::current()->Run(); | 
 |  | 
 |   EXPECT_FALSE(HasClientDownloadRequest()); | 
 |   // Overriden by flag: | 
 |   EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS)); | 
 | } | 
 |  | 
 | }  // namespace safe_browsing |