blob: 9c532f8142131b37a9bd902077332f033934e5e8 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/privacy_sandbox/tracking_protection_settings.h"
#include <memory>
#include <utility>
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/content_settings/core/test/content_settings_mock_provider.h"
#include "components/content_settings/core/test/content_settings_test_utils.h"
#include "components/prefs/testing_pref_service.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
#include "components/privacy_sandbox/tracking_protection_prefs.h"
#include "components/privacy_sandbox/tracking_protection_settings_observer.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/version_info/channel.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace privacy_sandbox {
namespace {
class MockTrackingProtectionSettingsObserver
: public TrackingProtectionSettingsObserver {
public:
MOCK_METHOD(void, OnDoNotTrackEnabledChanged, (), (override));
MOCK_METHOD(void, OnIpProtectionEnabledChanged, (), (override));
MOCK_METHOD(void, OnFpProtectionEnabledChanged, (), (override));
MOCK_METHOD(void, OnBlockAllThirdPartyCookiesChanged, (), (override));
MOCK_METHOD(void, OnTrackingProtection3pcdChanged, (), (override));
MOCK_METHOD(void, OnTrackingProtectionExceptionsChanged, (), (override));
};
class TrackingProtectionSettingsTest : public testing::Test {
public:
TrackingProtectionSettingsTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
content_settings::CookieSettings::RegisterProfilePrefs(prefs()->registry());
HostContentSettingsMap::RegisterProfilePrefs(prefs()->registry());
RegisterProfilePrefs(prefs()->registry());
}
GURL GetTestUrl() { return GURL("http://cool.things.com"); }
virtual std::vector<base::test::FeatureRef> EnabledFeatures() {
return {privacy_sandbox::kIpProtectionUx,
privacy_sandbox::kFingerprintingProtectionUx};
}
void SetUp() override {
host_content_settings_map_ = base::MakeRefCounted<HostContentSettingsMap>(
prefs(), /*is_off_the_record=*/false, /*store_last_modified=*/false,
/*restore_session=*/false,
/*should_record_metrics=*/false);
feature_list_.InitWithFeatures(EnabledFeatures(), {});
management_service_ = std::make_unique<policy::ManagementService>(
std::vector<std::unique_ptr<policy::ManagementStatusProvider>>());
tracking_protection_settings_ =
std::make_unique<TrackingProtectionSettings>(
prefs(), host_content_settings_map_.get(),
management_service_.get(),
/*is_incognito=*/false);
}
void TearDown() override {
host_content_settings_map_->ShutdownOnUIThread();
tracking_protection_settings_->Shutdown();
feature_list_.Reset();
}
TrackingProtectionSettings* tracking_protection_settings() {
return tracking_protection_settings_.get();
}
HostContentSettingsMap* host_content_settings_map() {
return host_content_settings_map_.get();
}
policy::ManagementService* management_service() {
return management_service_.get();
}
sync_preferences::TestingPrefServiceSyncable* prefs() { return &prefs_; }
private:
sync_preferences::TestingPrefServiceSyncable prefs_;
base::test::ScopedFeatureList feature_list_;
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
std::unique_ptr<policy::ManagementService> management_service_;
std::unique_ptr<TrackingProtectionSettings> tracking_protection_settings_;
base::test::SingleThreadTaskEnvironment task_environment_;
};
// Gets prefs
TEST_F(TrackingProtectionSettingsTest, ReturnsDoNotTrackStatus) {
EXPECT_FALSE(tracking_protection_settings()->IsDoNotTrackEnabled());
prefs()->SetBoolean(prefs::kEnableDoNotTrack, true);
EXPECT_TRUE(tracking_protection_settings()->IsDoNotTrackEnabled());
}
TEST_F(TrackingProtectionSettingsTest, ReturnsIpProtectionStatus) {
prefs()->SetBoolean(prefs::kIpProtectionEnabled, false);
EXPECT_FALSE(prefs()->GetBoolean(prefs::kIpProtectionEnabled));
EXPECT_FALSE(tracking_protection_settings()->IsIpProtectionEnabled());
prefs()->SetBoolean(prefs::kIpProtectionEnabled, true);
EXPECT_TRUE(tracking_protection_settings()->IsIpProtectionEnabled());
}
TEST_F(TrackingProtectionSettingsTest,
IsFpProtectionEnabledOnlyReturnsTrueInIncognito) {
prefs()->SetBoolean(prefs::kFingerprintingProtectionEnabled, true);
EXPECT_TRUE(TrackingProtectionSettings(prefs(), host_content_settings_map(),
management_service(),
/*is_incognito=*/true)
.IsFpProtectionEnabled());
EXPECT_FALSE(TrackingProtectionSettings(prefs(), host_content_settings_map(),
management_service(),
/*is_incognito=*/false)
.IsFpProtectionEnabled());
}
TEST_F(TrackingProtectionSettingsTest, ReturnsTrackingProtection3pcdStatus) {
EXPECT_FALSE(
tracking_protection_settings()->IsTrackingProtection3pcdEnabled());
prefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, true);
EXPECT_TRUE(
tracking_protection_settings()->IsTrackingProtection3pcdEnabled());
}
TEST_F(TrackingProtectionSettingsTest, AreAll3pcBlockedTrueInIncognito) {
prefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, true);
EXPECT_TRUE(TrackingProtectionSettings(prefs(), host_content_settings_map(),
management_service(),
/*is_incognito=*/true)
.AreAllThirdPartyCookiesBlocked());
EXPECT_FALSE(TrackingProtectionSettings(prefs(), host_content_settings_map(),
management_service(),
/*is_incognito=*/false)
.AreAllThirdPartyCookiesBlocked());
}
TEST_F(TrackingProtectionSettingsTest, AreAll3pcBlockedFalseOutside3pcd) {
prefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, false);
prefs()->SetBoolean(prefs::kBlockAll3pcToggleEnabled, true);
EXPECT_FALSE(
tracking_protection_settings()->AreAllThirdPartyCookiesBlocked());
}
// Content settings
using HasTrackingProtectionExceptionTest = TrackingProtectionSettingsTest;
TEST_F(HasTrackingProtectionExceptionTest,
ReturnsTrueWhenTrackingProtectionContentSettingForUrlIsAllow) {
host_content_settings_map()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(),
ContentSettingsPattern::FromURL(GetTestUrl()),
ContentSettingsType::TRACKING_PROTECTION,
ContentSetting::CONTENT_SETTING_ALLOW);
EXPECT_TRUE(tracking_protection_settings()->HasTrackingProtectionException(
GetTestUrl()));
}
TEST_F(HasTrackingProtectionExceptionTest, ReturnsFalseByDefault) {
EXPECT_FALSE(tracking_protection_settings()->HasTrackingProtectionException(
GetTestUrl()));
}
TEST_F(HasTrackingProtectionExceptionTest, FillsSettingInfo) {
content_settings::TestUtils::OverrideProvider(
host_content_settings_map(),
std::make_unique<content_settings::MockProvider>(),
content_settings::ProviderType::kPolicyProvider);
host_content_settings_map()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(),
ContentSettingsPattern::FromURL(GetTestUrl()),
ContentSettingsType::TRACKING_PROTECTION,
ContentSetting::CONTENT_SETTING_ALLOW);
content_settings::SettingInfo info;
EXPECT_TRUE(tracking_protection_settings()->HasTrackingProtectionException(
GetTestUrl(), &info));
EXPECT_EQ(info.primary_pattern, ContentSettingsPattern::Wildcard());
EXPECT_EQ(info.secondary_pattern,
ContentSettingsPattern::FromURL(GetTestUrl()));
EXPECT_EQ(info.source, content_settings::SettingSource::kPolicy);
}
TEST_F(TrackingProtectionSettingsTest,
AddTrackingProtectionExceptionAddsContentSetting) {
tracking_protection_settings()->AddTrackingProtectionException(GetTestUrl());
content_settings::SettingInfo info;
EXPECT_EQ(host_content_settings_map()->GetContentSetting(
GURL(), GetTestUrl(), ContentSettingsType::TRACKING_PROTECTION,
&info),
CONTENT_SETTING_ALLOW);
EXPECT_TRUE(info.metadata.expiration().is_null());
}
TEST_F(TrackingProtectionSettingsTest,
RemoveTrackingProtectionExceptionRemovesContentSetting) {
host_content_settings_map()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(),
ContentSettingsPattern::FromURLToSchemefulSitePattern(GetTestUrl()),
ContentSettingsType::TRACKING_PROTECTION,
ContentSetting::CONTENT_SETTING_ALLOW);
tracking_protection_settings()->RemoveTrackingProtectionException(
GetTestUrl());
EXPECT_EQ(host_content_settings_map()->GetContentSetting(
GURL(), GetTestUrl(), ContentSettingsType::TRACKING_PROTECTION),
CONTENT_SETTING_BLOCK);
}
// Tests that `GetTrackingProtectionExceptions` correctly filters its results.
// The method should only return content settings with a value of ALLOW, as
// these represent exceptions. It should not return settings of type
// TRACKING_PROTECTION with other values, such as BLOCK.
TEST_F(TrackingProtectionSettingsTest,
GetTrackingProtectionExceptionsReturnsOnlyAllowed) {
// Add a user-created exception, which is stored as a content setting with a
// value of ALLOW.
tracking_protection_settings()->AddTrackingProtectionException(GetTestUrl());
// In addition, manually add a content setting for the same feature but with a
// value of BLOCK. This simulates other potential rules that are not user
// exceptions.
host_content_settings_map()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(),
ContentSettingsPattern::FromURLToSchemefulSitePattern(
GURL("http://another.url.com")),
ContentSettingsType::TRACKING_PROTECTION, CONTENT_SETTING_BLOCK);
// Verify that the method correctly filters the results and returns only the
// ALLOW setting.
ContentSettingsForOneType exceptions =
tracking_protection_settings()->GetTrackingProtectionExceptions();
ASSERT_EQ(exceptions.size(), 1u);
EXPECT_EQ(exceptions[0].GetContentSetting(), CONTENT_SETTING_ALLOW);
}
// Sets prefs
TEST_F(TrackingProtectionSettingsTest,
DisablesTrackingProtection3pcdWhenEnterpriseControlEnabled) {
prefs()->SetBoolean(prefs::kPrivacySandboxRelatedWebsiteSetsEnabled, false);
prefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, true);
EXPECT_TRUE(
tracking_protection_settings()->IsTrackingProtection3pcdEnabled());
prefs()->SetManagedPref(prefs::kPrivacySandboxRelatedWebsiteSetsEnabled,
std::make_unique<base::Value>(false));
EXPECT_FALSE(
tracking_protection_settings()->IsTrackingProtection3pcdEnabled());
}
// Calls observers
TEST_F(TrackingProtectionSettingsTest, CorrectlyCallsObserversForDoNotTrack) {
MockTrackingProtectionSettingsObserver observer;
tracking_protection_settings()->AddObserver(&observer);
EXPECT_CALL(observer, OnDoNotTrackEnabledChanged());
prefs()->SetBoolean(prefs::kEnableDoNotTrack, true);
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_CALL(observer, OnDoNotTrackEnabledChanged());
prefs()->SetBoolean(prefs::kEnableDoNotTrack, false);
testing::Mock::VerifyAndClearExpectations(&observer);
}
TEST_F(TrackingProtectionSettingsTest, CorrectlyCallsObserversForIpProtection) {
MockTrackingProtectionSettingsObserver observer;
tracking_protection_settings()->AddObserver(&observer);
EXPECT_CALL(observer, OnIpProtectionEnabledChanged());
prefs()->SetBoolean(prefs::kIpProtectionEnabled, true);
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_CALL(observer, OnIpProtectionEnabledChanged());
prefs()->SetBoolean(prefs::kIpProtectionEnabled, false);
testing::Mock::VerifyAndClearExpectations(&observer);
}
TEST_F(TrackingProtectionSettingsTest, CorrectlyCallsObserversForFpp) {
MockTrackingProtectionSettingsObserver observer;
tracking_protection_settings()->AddObserver(&observer);
EXPECT_CALL(observer, OnFpProtectionEnabledChanged());
prefs()->SetBoolean(prefs::kFingerprintingProtectionEnabled, true);
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_CALL(observer, OnFpProtectionEnabledChanged());
prefs()->SetBoolean(prefs::kFingerprintingProtectionEnabled, false);
testing::Mock::VerifyAndClearExpectations(&observer);
}
TEST_F(TrackingProtectionSettingsTest, CorrectlyCallsObserversForBlockAll3pc) {
MockTrackingProtectionSettingsObserver observer;
tracking_protection_settings()->AddObserver(&observer);
EXPECT_CALL(observer, OnBlockAllThirdPartyCookiesChanged());
prefs()->SetBoolean(prefs::kBlockAll3pcToggleEnabled, true);
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_CALL(observer, OnBlockAllThirdPartyCookiesChanged());
prefs()->SetBoolean(prefs::kBlockAll3pcToggleEnabled, false);
testing::Mock::VerifyAndClearExpectations(&observer);
}
TEST_F(TrackingProtectionSettingsTest,
CorrectlyCallsObserversForTrackingProtectionExceptions) {
MockTrackingProtectionSettingsObserver observer;
tracking_protection_settings()->AddObserver(&observer);
EXPECT_CALL(observer, OnTrackingProtectionExceptionsChanged());
tracking_protection_settings()->AddTrackingProtectionException(GetTestUrl());
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_CALL(observer, OnTrackingProtectionExceptionsChanged());
tracking_protection_settings()->RemoveTrackingProtectionException(
GetTestUrl());
testing::Mock::VerifyAndClearExpectations(&observer);
}
TEST_F(TrackingProtectionSettingsTest,
CorrectlyCallsObserversForDirectContentSettingChanges) {
MockTrackingProtectionSettingsObserver observer;
tracking_protection_settings()->AddObserver(&observer);
EXPECT_CALL(observer, OnTrackingProtectionExceptionsChanged());
host_content_settings_map()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(),
ContentSettingsPattern::FromURLToSchemefulSitePattern(GetTestUrl()),
ContentSettingsType::TRACKING_PROTECTION, CONTENT_SETTING_ALLOW);
testing::Mock::VerifyAndClearExpectations(&observer);
}
// Rollback does not apply to iOS.
#if !BUILDFLAG(IS_IOS)
class TrackingProtectionSettingsRollbackTest
: public TrackingProtectionSettingsTest {
public:
std::vector<base::test::FeatureRef> EnabledFeatures() override {
return {privacy_sandbox::kRollBackModeB};
}
protected:
base::HistogramTester histogram_tester_;
};
TEST_F(TrackingProtectionSettingsRollbackTest,
Allowed3pcsDisables3pcdPrefAndEnablesRollbackUi) {
prefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, true);
TrackingProtectionSettings tps(prefs(), host_content_settings_map(),
management_service(),
/*is_incognito=*/false);
EXPECT_FALSE(prefs()->GetBoolean(prefs::kTrackingProtection3pcdEnabled));
EXPECT_TRUE(prefs()->GetBoolean(prefs::kShowRollbackUiModeB));
histogram_tester_.ExpectUniqueSample("Privacy.3PCD.RollbackNotice.ShouldShow",
true, 1);
}
TEST_F(TrackingProtectionSettingsRollbackTest,
Blocked3pcsIn3pcdDisables3pcdPrefAndRollbackUi) {
prefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, true);
prefs()->SetBoolean(prefs::kBlockAll3pcToggleEnabled, true);
TrackingProtectionSettings tps(prefs(), host_content_settings_map(),
management_service(),
/*is_incognito=*/false);
EXPECT_FALSE(prefs()->GetBoolean(prefs::kTrackingProtection3pcdEnabled));
EXPECT_FALSE(prefs()->GetBoolean(prefs::kShowRollbackUiModeB));
histogram_tester_.ExpectUniqueSample("Privacy.3PCD.RollbackNotice.ShouldShow",
false, 1);
}
TEST_F(TrackingProtectionSettingsRollbackTest,
Blocked3pcsDisables3pcdPrefAndRollbackUi) {
prefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, true);
prefs()->SetInteger(
prefs::kCookieControlsMode,
static_cast<int>(content_settings::CookieControlsMode::kBlockThirdParty));
TrackingProtectionSettings tps(prefs(), host_content_settings_map(),
management_service(),
/*is_incognito=*/false);
EXPECT_FALSE(prefs()->GetBoolean(prefs::kTrackingProtection3pcdEnabled));
EXPECT_FALSE(prefs()->GetBoolean(prefs::kShowRollbackUiModeB));
histogram_tester_.ExpectUniqueSample("Privacy.3PCD.RollbackNotice.ShouldShow",
false, 1);
}
#endif
} // namespace
} // namespace privacy_sandbox