blob: 6c5d1af553c5a1877d5b5d11661a72ca2e8fdaaf [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/safe_browsing/realtime/url_lookup_service.h"
#include "base/test/task_environment.h"
#include "content/public/test/browser_task_environment.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/platform_test.h"
namespace safe_browsing {
class RealTimeUrlLookupServiceTest : public PlatformTest {
public:
RealTimeUrlLookupServiceTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
PlatformTest::SetUp();
test_shared_loader_factory_ =
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_);
rt_service_ =
std::make_unique<RealTimeUrlLookupService>(test_shared_loader_factory_);
}
bool CanCheckUrl(const GURL& url) { return rt_service_->CanCheckUrl(url); }
void HandleLookupError() { rt_service_->HandleLookupError(); }
void HandleLookupSuccess() { rt_service_->HandleLookupSuccess(); }
bool IsInBackoffMode() { return rt_service_->IsInBackoffMode(); }
std::unique_ptr<RTLookupRequest> FillRequestProto(const GURL& url) {
return rt_service_->FillRequestProto(url);
}
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
std::unique_ptr<RealTimeUrlLookupService> rt_service_;
content::BrowserTaskEnvironment task_environment_;
};
TEST_F(RealTimeUrlLookupServiceTest, TestFillRequestProto) {
struct SanitizeUrlCase {
const char* url;
const char* expected_url;
} sanitize_url_cases[] = {
{"http://example.com/", "http://example.com/"},
{"http://user:pass@example.com/", "http://example.com/"},
{"http://%123:bar@example.com/", "http://example.com/"},
{"http://example.com#123", "http://example.com/"}};
for (size_t i = 0; i < base::size(sanitize_url_cases); i++) {
GURL url(sanitize_url_cases[i].url);
auto result = FillRequestProto(url);
EXPECT_EQ(sanitize_url_cases[i].expected_url, result->url());
EXPECT_EQ(RTLookupRequest::NAVIGATION, result->lookup_type());
}
}
TEST_F(RealTimeUrlLookupServiceTest, TestBackoffAndTimerReset) {
// Not in backoff at the beginning.
ASSERT_FALSE(IsInBackoffMode());
// Failure 1: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 2: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 3: Entered backoff.
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 299 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(298));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 300 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
}
TEST_F(RealTimeUrlLookupServiceTest, TestBackoffAndLookupSuccessReset) {
// Not in backoff at the beginning.
ASSERT_FALSE(IsInBackoffMode());
// Failure 1: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Lookup success resets the backoff counter.
HandleLookupSuccess();
EXPECT_FALSE(IsInBackoffMode());
// Failure 1: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 2: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Lookup success resets the backoff counter.
HandleLookupSuccess();
EXPECT_FALSE(IsInBackoffMode());
// Failure 1: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 2: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 3: Entered backoff.
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Lookup success resets the backoff counter.
HandleLookupSuccess();
EXPECT_FALSE(IsInBackoffMode());
}
TEST_F(RealTimeUrlLookupServiceTest, TestExponentialBackoff) {
///////////////////////////////
// Initial backoff: 300 seconds
///////////////////////////////
// Not in backoff at the beginning.
ASSERT_FALSE(IsInBackoffMode());
// Failure 1: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 2: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 3: Entered backoff.
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 299 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(298));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 300 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
/////////////////////////////////////
// Exponential backoff 1: 600 seconds
/////////////////////////////////////
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 599 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(598));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 600 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
//////////////////////////////////////
// Exponential backoff 2: 1200 seconds
//////////////////////////////////////
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1199 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1198));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 1200 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
///////////////////////////////////////////////////
// Exponential backoff 3: 1800 seconds (30 minutes)
///////////////////////////////////////////////////
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1799 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1798));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 1800 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
///////////////////////////////////////////////////
// Exponential backoff 4: 1800 seconds (30 minutes)
///////////////////////////////////////////////////
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1799 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1798));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 1800 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
}
TEST_F(RealTimeUrlLookupServiceTest, TestExponentialBackoffWithResetOnSuccess) {
///////////////////////////////
// Initial backoff: 300 seconds
///////////////////////////////
// Not in backoff at the beginning.
ASSERT_FALSE(IsInBackoffMode());
// Failure 1: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 2: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 3: Entered backoff.
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 299 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(298));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 300 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
/////////////////////////////////////
// Exponential backoff 1: 600 seconds
/////////////////////////////////////
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 599 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(598));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 600 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
// The next lookup is a success. This should reset the backoff duration to
// |kMinBackOffResetDurationInSeconds|
HandleLookupSuccess();
// Failure 1: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 2: No backoff.
HandleLookupError();
EXPECT_FALSE(IsInBackoffMode());
// Failure 3: Entered backoff.
HandleLookupError();
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 1 second.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(IsInBackoffMode());
// Backoff not reset after 299 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(298));
EXPECT_TRUE(IsInBackoffMode());
// Backoff should have been reset after 300 seconds.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_FALSE(IsInBackoffMode());
}
TEST_F(RealTimeUrlLookupServiceTest, TestGetSBThreatTypeForRTThreatType) {
EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE,
RealTimeUrlLookupService::GetSBThreatTypeForRTThreatType(
RTLookupResponse::ThreatInfo::WEB_MALWARE));
EXPECT_EQ(SB_THREAT_TYPE_URL_PHISHING,
RealTimeUrlLookupService::GetSBThreatTypeForRTThreatType(
RTLookupResponse::ThreatInfo::SOCIAL_ENGINEERING));
EXPECT_EQ(SB_THREAT_TYPE_URL_UNWANTED,
RealTimeUrlLookupService::GetSBThreatTypeForRTThreatType(
RTLookupResponse::ThreatInfo::UNWANTED_SOFTWARE));
EXPECT_EQ(SB_THREAT_TYPE_BILLING,
RealTimeUrlLookupService::GetSBThreatTypeForRTThreatType(
RTLookupResponse::ThreatInfo::UNCLEAR_BILLING));
}
TEST_F(RealTimeUrlLookupServiceTest, TestCanCheckUrl) {
struct CanCheckUrlCases {
const char* url;
bool can_check;
} can_check_url_cases[] = {{"ftp://example.test/path", false},
{"http://localhost/path", false},
{"http://localhost.localdomain/path", false},
{"http://127.0.0.1/path", false},
{"http://127.0.0.1:2222/path", false},
{"http://192.168.1.1/path", false},
{"http://172.16.2.2/path", false},
{"http://10.1.1.1/path", false},
{"http://10.1.1.1.1/path", true},
{"http://example.test/path", true},
{"https://example.test/path", true}};
for (size_t i = 0; i < base::size(can_check_url_cases); i++) {
GURL url(can_check_url_cases[i].url);
bool expected_can_check = can_check_url_cases[i].can_check;
EXPECT_EQ(expected_can_check, CanCheckUrl(url));
}
}
} // namespace safe_browsing