blob: ec96eb0446af821a40323efc5d10ed53d79600ae [file] [log] [blame]
// Copyright 2022 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 "base/bind.h"
#include "base/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "chrome/browser/safe_browsing/chrome_ping_manager_factory.h"
#include "chrome/browser/safe_browsing/chrome_user_population_helper.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h"
#include "components/safe_browsing/core/browser/ping_manager.h"
#include "components/safe_browsing/core/browser/test_safe_browsing_token_fetcher.h"
#include "components/safe_browsing/core/common/features.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "content/public/test/browser_task_environment.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using network::GetUploadData;
namespace safe_browsing {
class ChromePingManagerTest : public testing::Test {
protected:
void SetUp() override;
void TearDown() override;
void RunReportThreatDetailsTest(bool is_enhanced_protection,
bool is_signed_in,
bool is_csbrr_token_feature_enabled,
bool is_remove_cookies_feature_enabled,
bool expect_access_token,
bool expect_cookies_removed);
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfileManager> profile_manager_;
private:
void SetUpFeatureList(bool should_enable_csbrr_with_token,
bool should_enable_remove_cookies);
raw_ptr<TestingProfile> SetUpProfile(bool is_enhanced_protection,
bool is_signed_in);
TestSafeBrowsingTokenFetcher* SetUpTokenFetcher(PingManager* ping_manager);
scoped_refptr<safe_browsing::SafeBrowsingService> sb_service_;
base::test::ScopedFeatureList feature_list_;
};
void ChromePingManagerTest::SetUp() {
profile_manager_ = std::make_unique<TestingProfileManager>(
TestingBrowserProcess::GetGlobal());
ASSERT_TRUE(profile_manager_->SetUp());
ASSERT_TRUE(g_browser_process->profile_manager());
sb_service_ = base::MakeRefCounted<safe_browsing::TestSafeBrowsingService>();
TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService(sb_service_.get());
g_browser_process->safe_browsing_service()->Initialize();
WebUIInfoSingleton::GetInstance()->AddListenerForTesting();
}
void ChromePingManagerTest::TearDown() {
base::RunLoop().RunUntilIdle();
if (TestingBrowserProcess::GetGlobal()->safe_browsing_service()) {
TestingBrowserProcess::GetGlobal()->safe_browsing_service()->ShutDown();
TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService(nullptr);
}
feature_list_.Reset();
WebUIInfoSingleton::GetInstance()->ClearListenerForTesting();
}
void ChromePingManagerTest::SetUpFeatureList(
bool should_enable_csbrr_with_token,
bool should_enable_remove_cookies) {
std::vector<base::Feature> enabled_features = {};
std::vector<base::Feature> disabled_features = {};
if (should_enable_csbrr_with_token) {
enabled_features.push_back(kSafeBrowsingCsbrrWithToken);
} else {
disabled_features.push_back(kSafeBrowsingCsbrrWithToken);
}
if (should_enable_remove_cookies) {
enabled_features.push_back(kSafeBrowsingRemoveCookiesInAuthRequests);
} else {
disabled_features.push_back(kSafeBrowsingRemoveCookiesInAuthRequests);
}
feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
raw_ptr<TestingProfile> ChromePingManagerTest::SetUpProfile(
bool is_enhanced_protection,
bool is_signed_in) {
raw_ptr<TestingProfile> profile = profile_manager_->CreateTestingProfile(
"testing_profile", IdentityTestEnvironmentProfileAdaptor::
GetIdentityTestEnvironmentFactories());
if (is_enhanced_protection) {
SetSafeBrowsingState(profile->GetPrefs(),
SafeBrowsingState::ENHANCED_PROTECTION);
}
if (is_signed_in) {
IdentityTestEnvironmentProfileAdaptor adaptor(profile);
adaptor.identity_test_env()->MakePrimaryAccountAvailable(
"testing@gmail.com", signin::ConsentLevel::kSync);
}
return profile;
}
TestSafeBrowsingTokenFetcher* ChromePingManagerTest::SetUpTokenFetcher(
PingManager* ping_manager) {
auto token_fetcher = std::make_unique<TestSafeBrowsingTokenFetcher>();
auto* raw_token_fetcher = token_fetcher.get();
ping_manager->SetTokenFetcherForTesting(std::move(token_fetcher));
return raw_token_fetcher;
}
void ChromePingManagerTest::RunReportThreatDetailsTest(
bool is_enhanced_protection,
bool is_signed_in,
bool is_csbrr_token_feature_enabled,
bool is_remove_cookies_feature_enabled,
bool expect_access_token,
bool expect_cookies_removed) {
base::RunLoop csbrr_logged_run_loop;
base::HistogramTester histogram_tester;
SetUpFeatureList(is_csbrr_token_feature_enabled,
is_remove_cookies_feature_enabled);
raw_ptr<TestingProfile> profile =
SetUpProfile(is_enhanced_protection, is_signed_in);
auto* ping_manager = ChromePingManagerFactory::GetForBrowserContext(profile);
auto* raw_token_fetcher = SetUpTokenFetcher(ping_manager);
safe_browsing::WebUIInfoSingleton::GetInstance()
->SetOnCSBRRLoggedCallbackForTesting(csbrr_logged_run_loop.QuitClosure());
std::string access_token = "testing_access_token";
std::string input_report_content;
std::unique_ptr<ClientSafeBrowsingReportRequest> report =
std::make_unique<ClientSafeBrowsingReportRequest>();
// The report must be non-empty. The selected property to set is arbitrary.
report->set_type(ClientSafeBrowsingReportRequest::URL_PHISHING);
EXPECT_TRUE(report->SerializeToString(&input_report_content));
ClientSafeBrowsingReportRequest expected_report;
expected_report.ParseFromString(input_report_content);
*expected_report.mutable_population() =
safe_browsing::GetUserPopulationForProfile(profile);
std::string expected_report_content;
EXPECT_TRUE(expected_report.SerializeToString(&expected_report_content));
EXPECT_NE(input_report_content, expected_report_content);
network::TestURLLoaderFactory test_url_loader_factory;
test_url_loader_factory.SetInterceptor(
base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
EXPECT_EQ(GetUploadData(request), expected_report_content);
std::string header_value;
bool found_header = request.headers.GetHeader(
net::HttpRequestHeaders::kAuthorization, &header_value);
EXPECT_EQ(found_header, expect_access_token);
if (expect_access_token) {
EXPECT_EQ(header_value, "Bearer " + access_token);
}
EXPECT_EQ(request.credentials_mode,
expect_cookies_removed
? network::mojom::CredentialsMode::kOmit
: network::mojom::CredentialsMode::kInclude);
histogram_tester.ExpectUniqueSample(
"SafeBrowsing.ClientSafeBrowsingReport.RequestHasToken",
/*sample=*/expect_access_token,
/*expected_bucket_count=*/1);
}));
ping_manager->SetURLLoaderFactoryForTesting(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory));
PingManager::ReportThreatDetailsResult result =
ping_manager->ReportThreatDetails(std::move(report));
EXPECT_EQ(result, PingManager::ReportThreatDetailsResult::SUCCESS);
EXPECT_EQ(raw_token_fetcher->WasStartCalled(), expect_access_token);
if (expect_access_token) {
raw_token_fetcher->RunAccessTokenCallback(access_token);
}
csbrr_logged_run_loop.Run();
EXPECT_EQ(WebUIInfoSingleton::GetInstance()->csbrrs_sent().size(), 1u);
}
TEST_F(ChromePingManagerTest, ReportThreatDetailsWithAccessToken) {
RunReportThreatDetailsTest(/*is_enhanced_protection=*/true,
/*is_signed_in=*/true,
/*is_csbrr_token_feature_enabled=*/true,
/*is_remove_cookies_feature_enabled=*/true,
/*expect_access_token=*/true,
/*expect_cookies_removed=*/true);
}
TEST_F(ChromePingManagerTest,
ReportThreatDetailsWithAccessToken_RemoveCookiesFeatureDisabled) {
RunReportThreatDetailsTest(/*is_enhanced_protection=*/true,
/*is_signed_in=*/true,
/*is_csbrr_token_feature_enabled=*/true,
/*is_remove_cookies_feature_enabled=*/false,
/*expect_access_token=*/true,
/*expect_cookies_removed=*/false);
}
TEST_F(ChromePingManagerTest,
ReportThreatDetailsWithoutAccessToken_NotSignedIn) {
RunReportThreatDetailsTest(/*is_enhanced_protection=*/true,
/*is_signed_in=*/false,
/*is_csbrr_token_feature_enabled=*/true,
/*is_remove_cookies_feature_enabled=*/true,
/*expect_access_token=*/false,
/*expect_cookies_removed=*/false);
}
TEST_F(ChromePingManagerTest,
ReportThreatDetailsWithoutAccessToken_NotEnhancedProtection) {
RunReportThreatDetailsTest(/*is_enhanced_protection=*/false,
/*is_signed_in=*/true,
/*is_csbrr_token_feature_enabled=*/true,
/*is_remove_cookies_feature_enabled=*/true,
/*expect_access_token=*/false,
/*expect_cookies_removed=*/false);
}
TEST_F(ChromePingManagerTest, ReportThreatDetailsWithoutAccessToken_Incognito) {
raw_ptr<TestingProfile> profile = TestingProfile::Builder().BuildIncognito(
profile_manager_->CreateTestingProfile("testing_profile"));
EXPECT_EQ(ChromePingManagerFactory::GetForBrowserContext(profile), nullptr);
}
// TODO(crbug.com/1296615): remove test case when deprecating
// kSafeBrowsingCsbrrWithToken feature
TEST_F(ChromePingManagerTest,
ReportThreatDetailsWithoutAccessToken_CsbrrTokenFeatureDisabled) {
RunReportThreatDetailsTest(/*is_enhanced_protection=*/true,
/*is_signed_in=*/true,
/*is_csbrr_token_feature_enabled=*/false,
/*is_remove_cookies_feature_enabled=*/true,
/*expect_access_token=*/false,
/*expect_cookies_removed=*/false);
}
TEST_F(ChromePingManagerTest, ReportSafeBrowsingHit) {
raw_ptr<TestingProfile> profile =
profile_manager_->CreateTestingProfile("testing_profile");
auto* ping_manager = ChromePingManagerFactory::GetForBrowserContext(profile);
HitReport hit_report;
hit_report.post_data = "testing_hit_report_post_data";
// Threat type and source are arbitrary but specified so that determining the
// URL does not does throw an error due to input validation.
hit_report.threat_type = SB_THREAT_TYPE_URL_PHISHING;
hit_report.threat_source = ThreatSource::LOCAL_PVER4;
network::TestURLLoaderFactory test_url_loader_factory;
test_url_loader_factory.SetInterceptor(
base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
EXPECT_EQ(GetUploadData(request), hit_report.post_data);
}));
ping_manager->SetURLLoaderFactoryForTesting(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory));
ping_manager->ReportSafeBrowsingHit(hit_report);
}
} // namespace safe_browsing