client_side_detection_service_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/safe_browsing/client_side_detection_service.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/safe_browsing/client_model.pb.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/safe_browsing/csd.pb.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/sha2.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/test_url_fetcher_factory.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Invoke; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Mock; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::StrictMock; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace safe_browsing { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockClientSideDetectionService : public ClientSideDetectionService { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockClientSideDetectionService() : ClientSideDetectionService(NULL) {} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MockClientSideDetectionService() {} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD1(EndFetchModel, void(ClientModelStatus)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD1(ScheduleFetchModel, void(int64)); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Schedule(int64) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore the delay when testing. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartFetchModel(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Disable(int) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore the status. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetEnabledAndRefreshState(false); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockClientSideDetectionService); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION(QuitCurrentMessageLoop) { 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->Quit(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClientSideDetectionServiceTest : public testing::Test { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_thread_.reset(new content::TestBrowserThread(BrowserThread::FILE, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &msg_loop_)); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) factory_.reset(new net::FakeURLFetcherFactory(NULL)); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_thread_.reset(new content::TestBrowserThread(BrowserThread::UI, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &msg_loop_)); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.RunUntilIdle(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_thread_.reset(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_thread_.reset(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SendClientReportPhishingRequest(const GURL& phishing_url, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest* request = new ClientPhishingRequest(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->set_url(phishing_url.spec()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->set_client_score(score); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->set_is_phishing(true); // client thinks the URL is phishing. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SendClientReportPhishingRequest( 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ClientSideDetectionServiceTest::SendRequestDone, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) phishing_url_ = phishing_url; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // Waits until callback is called. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_phishing_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool SendClientReportMalwareRequest(const GURL& url) { 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<ClientMalwareRequest> request(new ClientMalwareRequest()); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->set_url(url.spec()); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) csd_service_->SendClientReportMalwareRequest( 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.release(), 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ClientSideDetectionServiceTest::SendMalwareRequestDone, 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) phishing_url_ = url; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.Run(); // Waits until callback is called. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return is_malware_; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetModelFetchResponse(std::string response_data, bool success) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) factory_->SetFakeResponse(ClientSideDetectionService::kClientModelUrl, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_data, success); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetClientReportPhishingResponse(std::string response_data, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) factory_->SetFakeResponse( 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::GetClientReportUrl( 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::kClientReportPhishingUrl), 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_data, success); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetClientReportMalwareResponse(std::string response_data, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) factory_->SetFakeResponse( 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::GetClientReportUrl( 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::kClientReportMalwareUrl), 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_data, success); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int GetNumReports(std::queue<base::Time>* report_times) { 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return csd_service_->GetNumReports(report_times); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<base::Time>& GetPhishingReportTimes() { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return csd_service_->phishing_report_times_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::queue<base::Time>& GetMalwareReportTimes() { 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return csd_service_->malware_report_times_; 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetCache(const GURL& gurl, bool is_phishing, base::Time time) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->cache_[gurl] = 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(is_phishing, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time)); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void TestCache() { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::PhishingCache& cache = csd_service_->cache_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time now = base::Time::Now(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time time = 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromDays( 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kNegativeCacheIntervalDays) + 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(5); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://first.url.com/")] = 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(false, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time)); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromDays( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kNegativeCacheIntervalDays) - 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromHours(1); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://second.url.com/")] = 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(false, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time)); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromMinutes( 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kPositiveCacheIntervalMinutes) - 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(5); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://third.url.com/")] = 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(true, time)); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromMinutes( 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kPositiveCacheIntervalMinutes) + 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(5); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://fourth.url.com/")] = 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(true, time)); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->UpdateCache(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3 elements should be in the cache, the first, third, and fourth. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(3U, cache.size()); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cache.find(GURL("http://first.url.com/")) != cache.end()); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cache.find(GURL("http://third.url.com/")) != cache.end()); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cache.find(GURL("http://fourth.url.com/")) != cache.end()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // While 3 elements remain, only the first and the fourth are actually 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_phishing; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->GetValidCachedResult( 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://first.url.com"), &is_phishing)); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(is_phishing); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->GetValidCachedResult( 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://third.url.com"), &is_phishing)); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->GetValidCachedResult( 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://fourth.url.com"), &is_phishing)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(is_phishing); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddFeature(const std::string& name, double value, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest* request) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest_Feature* feature = request->add_feature_map(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_name(name); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_value(value); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddNonModelFeature(const std::string& name, double value, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest* request) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest_Feature* feature = 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->add_non_model_feature_map(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_name(name); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_value(value); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ClientSideDetectionService> csd_service_; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::FakeURLFetcherFactory> factory_; 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop msg_loop_; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SendRequestDone(GURL phishing_url, bool is_phishing) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(phishing_url, phishing_url_); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_phishing_ = is_phishing; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Quit(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SendMalwareRequestDone(GURL url, bool is_malware) { 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(phishing_url_, url); 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_malware_ = is_malware; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.Quit(); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<content::TestBrowserThread> browser_thread_; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<content::TestBrowserThread> file_thread_; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL phishing_url_; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_phishing_; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_malware_; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, FetchModelTest) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to use a real service class here because we can't call 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the real EndFetchModel. It would reschedule a reload which might 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make the test flaky. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockClientSideDetectionService service; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, ScheduleFetchModel(_)).Times(1); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.SetEnabledAndRefreshState(true); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The model fetch failed. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse("blamodel", false /* failure */); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_FETCH_FAILED)) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Empty model file. 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetModelFetchResponse(std::string(), true /* success */); 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(service, EndFetchModel(ClientSideDetectionService::MODEL_EMPTY)) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model is too large. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse( 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(ClientSideDetectionService::kMaxModelSizeBytes + 1, 'x'), 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* success */); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_TOO_LARGE)) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unable to parse the model file. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse("Invalid model file", true /* success */); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_PARSE_ERROR)) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model that is missing some required fields (missing the version field). 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_max_words_per_term(4); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse(model.SerializePartialAsString(), true /* success */); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_MISSING_FIELDS)) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model that points to hashes that don't exist. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(10); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_hashes("bla"); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_page_term(1); // Should be 0 instead of 1. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse(model.SerializePartialAsString(), true /* success */); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_BAD_HASH_IDS)) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_page_term(0, 0); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model version number is wrong. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(-1); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), true /* success */); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_INVALID_VERSION_NUMBER)) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normal model. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(10); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), true /* success */); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_SUCCESS)) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model version number is decreasing. Set the model version number of the 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // model that is currently loaded in the service object to 11. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.model_.reset(new ClientSideModel(model)); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.model_->set_version(11); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), true /* success */); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_INVALID_VERSION_NUMBER)) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model version hasn't changed since the last reload. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.model_->set_version(10); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), true /* success */); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_NOT_CHANGED)) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, ServiceObjectDeletedBeforeCallbackDone) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse("bogus model", true /* success */); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_.get() != NULL); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We delete the client-side detection service class even though the callbacks 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // haven't run yet. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Waiting for the callbacks to run should not crash even if the service 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object is gone. 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.RunUntilIdle(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SendClientReportPhishingRequest) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse("bogus model", true /* success */); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url("http://a.com/"); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0.4f; // Some random client score. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time before = base::Time::Now(); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid response body from the server. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetClientReportPhishingResponse("invalid proto response", true /* success */); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(url, score)); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normal behavior. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingResponse response; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.set_phishy(true); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetClientReportPhishingResponse(response.SerializeAsString(), 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* success */); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(SendClientReportPhishingRequest(url, score)); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This request will fail 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL second_url("http://b.com/"); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.set_phishy(false); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetClientReportPhishingResponse(response.SerializeAsString(), 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false /* success */); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(second_url, score)); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time after = base::Time::Now(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that we have recorded all 3 requests within the correct time range. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<base::Time>& report_times = GetPhishingReportTimes(); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(3U, report_times.size()); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!report_times.empty()) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time time = report_times.back(); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.pop(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LE(before, time); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GE(after, time); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only the first url should be in the cache. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_phishing; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsInCache(url)); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->GetValidCachedResult(url, &is_phishing)); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(is_phishing); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsInCache(second_url)); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SendClientReportMalwareRequest) { 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetModelFetchResponse("bogus model", true /* success */); 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url("http://a.com/"); 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time before = base::Time::Now(); 42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invalid response body from the server. 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetClientReportMalwareResponse("invalid proto response", true /* success */); 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Normal behavior. 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientMalwareResponse response; 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.set_blacklist(true); 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), true); 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(SendClientReportMalwareRequest(url)); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This request will fail 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.set_blacklist(false); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false /* success */); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // server blacklist decision is false, and response is succesful 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.set_blacklist(false); 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), true); 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 44290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Check that we have recorded all 4 requests within the correct time range. 44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time after = base::Time::Now(); 44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::queue<base::Time>& report_times = GetMalwareReportTimes(); 44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(4U, report_times.size()); 44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Another normal behavior will fail because of the limit is hit 44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) response.set_blacklist(true); 45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), true); 45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) report_times = GetMalwareReportTimes(); 45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(4U, report_times.size()); 45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) while (!report_times.empty()) { 45690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time time = report_times.back(); 45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) report_times.pop(); 45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_LE(before, time); 45990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_GE(after, time); 46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, GetNumReportTest) { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse("bogus model", true /* success */); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<base::Time>& report_times = GetPhishingReportTimes(); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time now = base::Time::Now(); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta twenty_five_hours = base::TimeDelta::FromHours(25); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now - twenty_five_hours); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now - twenty_five_hours); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(2, GetNumReports(&report_times)); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, CacheTest) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse("bogus model", true /* success */); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestCache(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, IsPrivateIPAddress) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse("bogus model", true /* success */); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("10.1.2.3")); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("127.0.0.1")); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("172.24.3.4")); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("192.168.1.1")); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("fc00::")); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("fec0::")); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("fec0:1:2::3")); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("::1")); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsPrivateIPAddress("1.2.3.4")); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsPrivateIPAddress("200.1.1.1")); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsPrivateIPAddress("2001:0db8:ac10:fe01::")); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the address can't be parsed, the default is true. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("blah")); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SetBadSubnets) { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::BadSubnetMap bad_subnets; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::SetBadSubnets(model, &bad_subnets); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0U, bad_subnets.size()); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bad subnets are skipped. 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel::IPSubnet* subnet = model.add_bad_subnet(); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(130); // Invalid size. 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(-1); // Invalid size. 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(16, '.')); // Invalid len. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(64); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::SetBadSubnets(model, &bad_subnets); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0U, bad_subnets.size()); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(64); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, ',')); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(64); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(128); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(100); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::SetBadSubnets(model, &bad_subnets); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(3U, bad_subnets.size()); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::BadSubnetMap::const_iterator it; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string mask = std::string(8, '\xFF') + std::string(8, '\x00'); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets.count(mask)); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, '.'))); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, ','))); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mask = std::string(16, '\xFF'); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets.count(mask)); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, '.'))); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mask = std::string(12, '\xFF') + "\xF0" + std::string(3, '\x00'); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets.count(mask)); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, '.'))); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, IsBadIpAddress) { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IPv6 exact match for: 2620:0:1000:3103:21a:a0ff:fe10:786e. 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel::IPSubnet* subnet = model.add_bad_subnet(); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(crypto::SHA256HashString(std::string( 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\x26\x20\x00\x00\x10\x00\x31\x03\x02\x1a\xa0\xff\xfe\x10\x78\x6e", 16))); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(128); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IPv6 prefix match for: fe80::21a:a0ff:fe10:786e/64. 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(crypto::SHA256HashString(std::string( 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(64); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IPv4 exact match for ::ffff:192.0.2.128. 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(crypto::SHA256HashString(std::string( 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xc0\x00\x02\x80", 16))); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(128); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IPv4 prefix match (/8) for ::ffff:192.1.1.0. 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(crypto::SHA256HashString(std::string( 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xc0\x01\x01\x00", 16))); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(120); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IPv4 prefix match (/9) for ::ffff:192.1.122.0. 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(crypto::SHA256HashString(std::string( 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xc0\x01\x7a\x00", 16))); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(119); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IPv4 prefix match (/15) for ::ffff:192.1.128.0. 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(crypto::SHA256HashString(std::string( 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xc0\x01\x80\x00", 16))); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(113); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::SetBadSubnets( 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model, &(csd_service_->bad_subnets_)); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress("blabla")); 603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress(std::string())); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress( 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "2620:0:1000:3103:21a:a0ff:fe10:786e")); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress( 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "2620:0:1000:3103:21a:a0ff:fe10:786f")); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("fe80::21a:a0ff:fe10:786e")); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("fe80::31a:a0ff:fe10:786e")); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("fe80::21a:a0ff:fe10:786f")); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress("fe81::21a:a0ff:fe10:786e")); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.0.2.128")); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("::ffff:192.0.2.128")); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress("192.0.2.129")); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.1.0")); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.1.255")); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.1.10")); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("::ffff:192.1.1.2")); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress("192.1.121.255")); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.122.0")); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("::ffff:192.1.122.1")); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.122.255")); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.123.0")); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.123.255")); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress("192.1.124.0")); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress("192.1.127.255")); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.128.0")); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("::ffff:192.1.128.1")); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.128.255")); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.255.0")); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsBadIpAddress("192.1.255.255")); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsBadIpAddress("192.2.0.0")); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, ModelHasValidHashIds) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_hashes("bla"); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_page_term(0); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_page_term(-1); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_page_term(1, 1); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_page_term(1, 0); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test bad rules. 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_hashes("blu"); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel::Rule* rule = model.add_rule(); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(0); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(1); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_weight(0.1f); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule = model.add_rule(); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(0); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(1); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(-1); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_weight(0.2f); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_feature(2, 2); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_feature(2, 1); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SetEnabledAndRefreshState) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the model isn't downloaded until the service is enabled. 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->enabled()); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() == NULL); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use a MockClientSideDetectionService for the rest of the test, to avoid 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the scheduling delay. 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockClientSideDetectionService* service = 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new StrictMock<MockClientSideDetectionService>(); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(service); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->enabled()); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() == NULL); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No calls expected yet. 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(10); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_max_words_per_term(4); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), true /* success */); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, ScheduleFetchModel(_)) 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Schedule)); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, EndFetchModel( 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_SUCCESS)) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() != NULL); 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that enabling again doesn't request the model. 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No calls expected. 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that disabling the service cancels pending requests. 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, ScheduleFetchModel(_)) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Schedule)); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(false); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() != NULL); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(false); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() == NULL); 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.RunUntilIdle(); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No calls expected. 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Requests always return false when the service is disabled. 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingResponse response; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.set_phishy(true); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetClientReportPhishingResponse(response.SerializeAsString(), 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* success */); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(GURL("http://a.com/"), 0.4f)); 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pending requests also return false if the service is disabled before they 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // report back. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, ScheduleFetchModel(_)) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Schedule)); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, EndFetchModel( 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_NOT_CHANGED)) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Disable)); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(GURL("http://a.com/"), 0.4f)); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace safe_browsing 745