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" 139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/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" 200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/http/http_status_code.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" 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Invoke; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Mock; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::StrictMock; 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using ::testing::_; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace safe_browsing { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockClientSideDetectionService : public ClientSideDetectionService { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockClientSideDetectionService() : ClientSideDetectionService(NULL) {} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MockClientSideDetectionService() {} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD1(EndFetchModel, void(ClientModelStatus)); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD1(ScheduleFetchModel, void(int64)); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Schedule(int64) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore the delay when testing. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartFetchModel(); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Disable(int) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore the status. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetEnabledAndRefreshState(false); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockClientSideDetectionService); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION(QuitCurrentMessageLoop) { 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->Quit(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClientSideDetectionServiceTest : public testing::Test { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_thread_.reset(new content::TestBrowserThread(BrowserThread::FILE, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &msg_loop_)); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) factory_.reset(new net::FakeURLFetcherFactory(NULL)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_thread_.reset(new content::TestBrowserThread(BrowserThread::UI, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &msg_loop_)); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.RunUntilIdle(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_thread_.reset(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_thread_.reset(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SendClientReportPhishingRequest(const GURL& phishing_url, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest* request = new ClientPhishingRequest(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->set_url(phishing_url.spec()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->set_client_score(score); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->set_is_phishing(true); // client thinks the URL is phishing. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SendClientReportPhishingRequest( 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ClientSideDetectionServiceTest::SendRequestDone, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) phishing_url_ = phishing_url; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // Waits until callback is called. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_phishing_; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool SendClientReportMalwareRequest(const GURL& url) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<ClientMalwareRequest> request(new ClientMalwareRequest()); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->set_url(url.spec()); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) csd_service_->SendClientReportMalwareRequest( 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.release(), 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ClientSideDetectionServiceTest::SendMalwareRequestDone, 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) phishing_url_ = url; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.Run(); // Waits until callback is called. 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return is_malware_; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) void SetModelFetchResponse(std::string response_data, 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::HttpStatusCode response_code, 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::Status status) { 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) factory_->SetFakeResponse(GURL(ClientSideDetectionService::kClientModelUrl), 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) response_data, response_code, status); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetClientReportPhishingResponse(std::string response_data, 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::HttpStatusCode response_code, 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::Status status) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) factory_->SetFakeResponse( 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::GetClientReportUrl( 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::kClientReportPhishingUrl), 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) response_data, response_code, status); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetClientReportMalwareResponse(std::string response_data, 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::HttpStatusCode response_code, 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::Status status) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) factory_->SetFakeResponse( 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::GetClientReportUrl( 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientSideDetectionService::kClientReportMalwareUrl), 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) response_data, response_code, status); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int GetNumReports(std::queue<base::Time>* report_times) { 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return csd_service_->GetNumReports(report_times); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<base::Time>& GetPhishingReportTimes() { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return csd_service_->phishing_report_times_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::queue<base::Time>& GetMalwareReportTimes() { 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return csd_service_->malware_report_times_; 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetCache(const GURL& gurl, bool is_phishing, base::Time time) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->cache_[gurl] = 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(is_phishing, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void TestCache() { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::PhishingCache& cache = csd_service_->cache_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time now = base::Time::Now(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time time = 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromDays( 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kNegativeCacheIntervalDays) + 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(5); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://first.url.com/")] = 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(false, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time)); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromDays( 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kNegativeCacheIntervalDays) - 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromHours(1); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://second.url.com/")] = 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(false, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time)); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromMinutes( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kPositiveCacheIntervalMinutes) - 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(5); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://third.url.com/")] = 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(true, time)); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now - base::TimeDelta::FromMinutes( 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::kPositiveCacheIntervalMinutes) + 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(5); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache[GURL("http://fourth.url.com/")] = 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_linked_ptr(new ClientSideDetectionService::CacheState(true, time)); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->UpdateCache(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3 elements should be in the cache, the first, third, and fourth. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(3U, cache.size()); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cache.find(GURL("http://first.url.com/")) != cache.end()); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cache.find(GURL("http://third.url.com/")) != cache.end()); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cache.find(GURL("http://fourth.url.com/")) != cache.end()); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // While 3 elements remain, only the first and the fourth are actually 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_phishing; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->GetValidCachedResult( 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://first.url.com"), &is_phishing)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(is_phishing); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->GetValidCachedResult( 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://third.url.com"), &is_phishing)); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->GetValidCachedResult( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("http://fourth.url.com"), &is_phishing)); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(is_phishing); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddFeature(const std::string& name, double value, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest* request) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest_Feature* feature = request->add_feature_map(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_name(name); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_value(value); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddNonModelFeature(const std::string& name, double value, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest* request) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingRequest_Feature* feature = 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->add_non_model_feature_map(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_name(name); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->set_value(value); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void CheckConfirmedMalwareUrl(GURL url) { 222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ASSERT_EQ(confirmed_malware_url_, url); 223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ClientSideDetectionService> csd_service_; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::FakeURLFetcherFactory> factory_; 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop msg_loop_; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SendRequestDone(GURL phishing_url, bool is_phishing) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(phishing_url, phishing_url_); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_phishing_ = is_phishing; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Quit(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void SendMalwareRequestDone(GURL original_url, GURL malware_url, 238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_malware) { 239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ASSERT_EQ(phishing_url_, original_url); 240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) confirmed_malware_url_ = malware_url; 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_malware_ = is_malware; 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.Quit(); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<content::TestBrowserThread> browser_thread_; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<content::TestBrowserThread> file_thread_; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL phishing_url_; 249424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GURL confirmed_malware_url_; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_phishing_; 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_malware_; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, FetchModelTest) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to use a real service class here because we can't call 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the real EndFetchModel. It would reschedule a reload which might 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make the test flaky. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockClientSideDetectionService service; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, ScheduleFetchModel(_)).Times(1); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.SetEnabledAndRefreshState(true); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The model fetch failed. 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("blamodel", net::HTTP_INTERNAL_SERVER_ERROR, 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::FAILED); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_FETCH_FAILED)) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Empty model file. 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(std::string(), net::HTTP_OK, 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(service, EndFetchModel(ClientSideDetectionService::MODEL_EMPTY)) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model is too large. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetModelFetchResponse( 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(ClientSideDetectionService::kMaxModelSizeBytes + 1, 'x'), 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::HTTP_OK, net::URLRequestStatus::SUCCESS); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_TOO_LARGE)) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unable to parse the model file. 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("Invalid model file", net::HTTP_OK, 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_PARSE_ERROR)) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model that is missing some required fields (missing the version field). 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_max_words_per_term(4); 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(model.SerializePartialAsString(), net::HTTP_OK, 306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_MISSING_FIELDS)) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model that points to hashes that don't exist. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(10); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_hashes("bla"); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_page_term(1); // Should be 0 instead of 1. 318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(model.SerializePartialAsString(), net::HTTP_OK, 319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_BAD_HASH_IDS)) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_page_term(0, 0); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model version number is wrong. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(-1); 330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), net::HTTP_OK, 331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_INVALID_VERSION_NUMBER)) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normal model. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(10); 341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), net::HTTP_OK, 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_SUCCESS)) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model version number is decreasing. Set the model version number of the 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // model that is currently loaded in the service object to 11. 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.model_.reset(new ClientSideModel(model)); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.model_->set_version(11); 354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), net::HTTP_OK, 355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_INVALID_VERSION_NUMBER)) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Model version hasn't changed since the last reload. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.model_->set_version(10); 365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), net::HTTP_OK, 366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(service, EndFetchModel( 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_NOT_CHANGED)) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service.StartFetchModel(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(&service); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, ServiceObjectDeletedBeforeCallbackDone) { 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("bogus model", net::HTTP_OK, 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_.get() != NULL); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We delete the client-side detection service class even though the callbacks 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // haven't run yet. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Waiting for the callbacks to run should not crash even if the service 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object is gone. 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.RunUntilIdle(); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SendClientReportPhishingRequest) { 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("bogus model", net::HTTP_OK, 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url("http://a.com/"); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0.4f; // Some random client score. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time before = base::Time::Now(); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid response body from the server. 401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetClientReportPhishingResponse("invalid proto response", net::HTTP_OK, 402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(url, score)); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normal behavior. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingResponse response; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.set_phishy(true); 408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetClientReportPhishingResponse(response.SerializeAsString(), net::HTTP_OK, 409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(SendClientReportPhishingRequest(url, score)); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This request will fail 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL second_url("http://b.com/"); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.set_phishy(false); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetClientReportPhishingResponse(response.SerializeAsString(), 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::HTTP_INTERNAL_SERVER_ERROR, 417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::FAILED); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(second_url, score)); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time after = base::Time::Now(); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that we have recorded all 3 requests within the correct time range. 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<base::Time>& report_times = GetPhishingReportTimes(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(3U, report_times.size()); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!report_times.empty()) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time time = report_times.back(); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.pop(); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LE(before, time); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GE(after, time); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only the first url should be in the cache. 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_phishing; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsInCache(url)); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->GetValidCachedResult(url, &is_phishing)); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(is_phishing); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsInCache(second_url)); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SendClientReportMalwareRequest) { 441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("bogus model", net::HTTP_OK, 442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url("http://a.com/"); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time before = base::Time::Now(); 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invalid response body from the server. 449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetClientReportMalwareResponse("invalid proto response", net::HTTP_OK, 450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Missing bad_url. 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientMalwareResponse response; 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.set_blacklist(true); 456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), net::HTTP_OK, 457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Normal behavior. 461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) response.set_blacklist(true); 462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) response.set_bad_url("http://response-bad.com/"); 463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), net::HTTP_OK, 464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(SendClientReportMalwareRequest(url)); 466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) CheckConfirmedMalwareUrl(GURL("http://response-bad.com/")); 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This request will fail 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.set_blacklist(false); 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), 471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::HTTP_INTERNAL_SERVER_ERROR, 472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::FAILED); 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 475effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Server blacklist decision is false, and response is successful 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.set_blacklist(false); 477f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetClientReportMalwareResponse(response.SerializeAsString(), net::HTTP_OK, 478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(SendClientReportMalwareRequest(url)); 48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 481effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Check that we have recorded all 5 requests within the correct time range. 48290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time after = base::Time::Now(); 48390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::queue<base::Time>& report_times = GetMalwareReportTimes(); 484effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_EQ(5U, report_times.size()); 48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 486effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Check that the malware report limit was reached. 487effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_TRUE(csd_service_->OverMalwareReportLimit()); 48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) report_times = GetMalwareReportTimes(); 490effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_EQ(5U, report_times.size()); 49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) while (!report_times.empty()) { 49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time time = report_times.back(); 49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) report_times.pop(); 49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_LE(before, time); 49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_GE(after, time); 49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, GetNumReportTest) { 500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("bogus model", net::HTTP_OK, 501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<base::Time>& report_times = GetPhishingReportTimes(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time now = base::Time::Now(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta twenty_five_hours = base::TimeDelta::FromHours(25); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now - twenty_five_hours); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now - twenty_five_hours); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_times.push(now); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(2, GetNumReports(&report_times)); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, CacheTest) { 516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("bogus model", net::HTTP_OK, 517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestCache(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, IsPrivateIPAddress) { 524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse("bogus model", net::HTTP_OK, 525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("10.1.2.3")); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("127.0.0.1")); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("172.24.3.4")); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("192.168.1.1")); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("fc00::")); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("fec0::")); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("fec0:1:2::3")); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("::1")); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsPrivateIPAddress("1.2.3.4")); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsPrivateIPAddress("200.1.1.1")); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->IsPrivateIPAddress("2001:0db8:ac10:fe01::")); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the address can't be parsed, the default is true. 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->IsPrivateIPAddress("blah")); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SetBadSubnets) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::BadSubnetMap bad_subnets; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::SetBadSubnets(model, &bad_subnets); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0U, bad_subnets.size()); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bad subnets are skipped. 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel::IPSubnet* subnet = model.add_bad_subnet(); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(130); // Invalid size. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(-1); // Invalid size. 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(16, '.')); // Invalid len. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(64); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::SetBadSubnets(model, &bad_subnets); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0U, bad_subnets.size()); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(64); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, ',')); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(64); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(128); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet = model.add_bad_subnet(); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_prefix(std::string(crypto::kSHA256Length, '.')); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subnet->set_size(100); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::SetBadSubnets(model, &bad_subnets); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(3U, bad_subnets.size()); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::BadSubnetMap::const_iterator it; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string mask = std::string(8, '\xFF') + std::string(8, '\x00'); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets.count(mask)); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, '.'))); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, ','))); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mask = std::string(16, '\xFF'); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets.count(mask)); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, '.'))); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mask = std::string(12, '\xFF') + "\xF0" + std::string(3, '\x00'); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets.count(mask)); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(bad_subnets[mask].count(std::string(crypto::kSHA256Length, '.'))); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, ModelHasValidHashIds) { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_hashes("bla"); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_page_term(0); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_page_term(-1); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_page_term(1, 1); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_page_term(1, 0); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test bad rules. 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.add_hashes("blu"); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel::Rule* rule = model.add_rule(); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(0); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(1); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_weight(0.1f); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule = model.add_rule(); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(0); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(1); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->add_feature(-1); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_weight(0.2f); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_feature(2, 2); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rule->set_feature(2, 1); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ClientSideDetectionService::ModelHasValidHashIds(model)); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ClientSideDetectionServiceTest, SetEnabledAndRefreshState) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the model isn't downloaded until the service is enabled. 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(ClientSideDetectionService::Create(NULL)); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->enabled()); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() == NULL); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use a MockClientSideDetectionService for the rest of the test, to avoid 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the scheduling delay. 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockClientSideDetectionService* service = 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new StrictMock<MockClientSideDetectionService>(); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_.reset(service); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(csd_service_->enabled()); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() == NULL); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No calls expected yet. 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideModel model; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_version(10); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model.set_max_words_per_term(4); 656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetModelFetchResponse(model.SerializeAsString(), net::HTTP_OK, 657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, ScheduleFetchModel(_)) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Schedule)); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, EndFetchModel( 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_SUCCESS)) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(QuitCurrentMessageLoop()); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() != NULL); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_loop_.Run(); // EndFetchModel will quit the message loop. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that enabling again doesn't request the model. 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No calls expected. 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that disabling the service cancels pending requests. 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, ScheduleFetchModel(_)) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Schedule)); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(false); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() != NULL); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(false); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(csd_service_->model_fetcher_.get() == NULL); 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_loop_.RunUntilIdle(); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No calls expected. 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Requests always return false when the service is disabled. 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientPhishingResponse response; 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.set_phishy(true); 689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetClientReportPhishingResponse(response.SerializeAsString(), net::HTTP_OK, 690f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::URLRequestStatus::SUCCESS); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(GURL("http://a.com/"), 0.4f)); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pending requests also return false if the service is disabled before they 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // report back. 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, ScheduleFetchModel(_)) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Schedule)); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(*service, EndFetchModel( 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSideDetectionService::MODEL_NOT_CHANGED)) 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(service, &MockClientSideDetectionService::Disable)); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) csd_service_->SetEnabledAndRefreshState(true); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(SendClientReportPhishingRequest(GURL("http://a.com/"), 0.4f)); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mock::VerifyAndClearExpectations(service); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace safe_browsing 705