Add Auto Shred website setting (#30759)

* Add Brave Auto Shred content setting and unit tests.
This commit is contained in:
StephenHeaps
2025-10-28 15:40:46 -07:00
committed by GitHub
parent 08125e0c40
commit 7b09fa88f4
17 changed files with 237 additions and 1 deletions
@@ -218,6 +218,19 @@ TEST_F(BraveContentSettingsRegistryTest, GetInitialDefaultSetting) {
info = registry()->Get(ContentSettingsType::BRAVE_SPEEDREADER);
EXPECT_EQ(CONTENT_SETTING_ASK, info->GetInitialDefaultSetting());
}
{
SCOPED_TRACE("Content setting: BRAVE_AUTO_SHRED");
const WebsiteSettingsInfo* ws_info =
website_settings_registry()->Get(ContentSettingsType::BRAVE_AUTO_SHRED);
const auto initial_value = brave_shields::AutoShredSetting::FromValue(
ws_info->initial_default_value());
EXPECT_EQ(brave_shields::mojom::AutoShredMode::NEVER, initial_value);
EXPECT_EQ(brave_shields::mojom::AutoShredMode::NEVER,
brave_shields::AutoShredSetting::kDefaultValue);
EXPECT_EQ(ws_info->initial_default_value(),
brave_shields::AutoShredSetting::DefaultValue());
}
}
} // namespace content_settings
@@ -35,6 +35,7 @@
{ContentSettingsType::BRAVE_REMEMBER_1P_STORAGE, nullptr}, \
{ContentSettingsType::BRAVE_LOCALHOST_ACCESS, "localhostAccess"}, \
{ContentSettingsType::BRAVE_OPEN_AI_CHAT, "braveOpenAIChat"}, \
{ContentSettingsType::BRAVE_AUTO_SHRED, nullptr}, \
{ContentSettingsType::BRAVE_WEBCOMPAT_NONE, nullptr}, \
{ContentSettingsType::BRAVE_WEBCOMPAT_AUDIO, nullptr}, \
{ContentSettingsType::BRAVE_WEBCOMPAT_CANVAS, nullptr}, \
@@ -403,6 +403,16 @@ void ContentSettingsRegistry::BraveInit() {
WebsiteSettingsRegistry::PLATFORM_IOS,
WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
website_settings_registry_->Register(
ContentSettingsType::BRAVE_AUTO_SHRED, brave_shields::kBraveAutoShred,
brave_shields::AutoShredSetting::DefaultValue(),
WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE,
WebsiteSettingsRegistry::DESKTOP |
WebsiteSettingsRegistry::PLATFORM_ANDROID |
WebsiteSettingsRegistry::PLATFORM_IOS,
WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
#if BUILDFLAG(ENABLE_PSST)
if (base::FeatureList::IsEnabled(psst::features::kEnablePsst)) {
website_settings_registry_->Register(
@@ -46,6 +46,7 @@ static_assert(static_cast<int>(ContentSettingsType::kMaxValue) <
{ContentSettingsType::BRAVE_REMEMBER_1P_STORAGE, brave_value(13)}, \
{ContentSettingsType::BRAVE_LOCALHOST_ACCESS, brave_value(14)}, \
{ContentSettingsType::BRAVE_OPEN_AI_CHAT, brave_value(15)}, \
{ContentSettingsType::BRAVE_AUTO_SHRED, brave_value(16)}, \
/* Begin webcompat items */ \
{ContentSettingsType::BRAVE_WEBCOMPAT_NONE, brave_value(50)}, \
{ContentSettingsType::BRAVE_WEBCOMPAT_AUDIO, brave_value(51)}, \
@@ -27,6 +27,8 @@ enum ContentSettingsType {
// Allow a site to open AI Chat (in side panel on Desktop).
// This is limited to Brave Search only.
BRAVE_OPEN_AI_CHAT,
// Allow a site data to be cleared on last tab closed, or app exit.
BRAVE_AUTO_SHRED,
BRAVE_WEBCOMPAT_NONE,
BRAVE_WEBCOMPAT_AUDIO,
@@ -168,4 +168,36 @@ bool BraveShieldsSettingsService::IsNoScriptEnabled(const GURL& url) {
return control_type != ControlType::ALLOW;
}
void BraveShieldsSettingsService::SetDefaultAutoShredMode(
mojom::AutoShredMode mode) {
SetAutoShredMode(mode, GURL());
}
mojom::AutoShredMode BraveShieldsSettingsService::GetDefaultAutoShredMode() {
return GetAutoShredMode(GURL());
}
void BraveShieldsSettingsService::SetAutoShredMode(mojom::AutoShredMode mode,
const GURL& url) {
// Shred and AutoShred delete data at the eTLD+1 boundary, because thats
// the Webs cookie boundary, so we must use the domain pattern to align
// with how browsers enforce storage boundaries.
auto primary_pattern = content_settings::CreateDomainPattern(url);
if (!primary_pattern.IsValid()) {
return;
}
host_content_settings_map_->SetWebsiteSettingCustomScope(
primary_pattern, ContentSettingsPattern::Wildcard(),
AutoShredSetting::kContentSettingsType, AutoShredSetting::ToValue(mode));
}
mojom::AutoShredMode BraveShieldsSettingsService::GetAutoShredMode(
const GURL& url) {
return AutoShredSetting::FromValue(
host_content_settings_map_->GetWebsiteSetting(
url, GURL(), AutoShredSetting::kContentSettingsType));
}
} // namespace brave_shields
@@ -47,6 +47,12 @@ class BraveShieldsSettingsService : public KeyedService {
void SetNoScriptEnabled(bool is_enabled, const GURL& url);
bool IsNoScriptEnabled(const GURL& url);
void SetDefaultAutoShredMode(mojom::AutoShredMode mode);
mojom::AutoShredMode GetDefaultAutoShredMode();
void SetAutoShredMode(mojom::AutoShredMode mode, const GURL& url);
mojom::AutoShredMode GetAutoShredMode(const GURL& url);
private:
const raw_ref<HostContentSettingsMap>
host_content_settings_map_; // NOT OWNED
@@ -17,6 +17,7 @@
#include "url/gurl.h"
using brave_shields::mojom::AdBlockMode;
using brave_shields::mojom::AutoShredMode;
using brave_shields::mojom::FingerprintMode;
class BraveShieldsSettingsServiceTest : public testing::Test {
@@ -50,6 +51,13 @@ class BraveShieldsSettingsServiceTest : public testing::Test {
return brave_shields_settings_.get();
}
base::Value AutoShredDictFrom(AutoShredMode mode) {
base::Value dict(base::Value::Type::DICT);
dict.GetDict().Set(brave_shields::AutoShredSetting::kName,
static_cast<int>(mode));
return dict;
}
private:
base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple local_state_;
@@ -303,3 +311,76 @@ TEST_F(BraveShieldsSettingsServiceTest, NoScriptsEnabledByDefault) {
kTestUrl),
brave_shields::ControlType::ALLOW);
}
TEST_F(BraveShieldsSettingsServiceTest, AutoShredMode) {
// verify the initial values
EXPECT_EQ(brave_shields_settings()->GetAutoShredMode(kTestUrl),
AutoShredMode::NEVER);
EXPECT_EQ(GetHostContentSettingsMap()->GetWebsiteSetting(
kTestUrl, GURL(),
brave_shields::AutoShredSetting::kContentSettingsType),
AutoShredDictFrom(AutoShredMode::NEVER));
brave_shields_settings()->SetAutoShredMode(AutoShredMode::LAST_TAB_CLOSED,
kTestUrl);
EXPECT_EQ(brave_shields_settings()->GetAutoShredMode(kTestUrl),
AutoShredMode::LAST_TAB_CLOSED);
// verify underlying AutoShredMode is updated
EXPECT_EQ(GetHostContentSettingsMap()->GetWebsiteSetting(
kTestUrl, GURL(),
brave_shields::AutoShredSetting::kContentSettingsType),
AutoShredDictFrom(AutoShredMode::LAST_TAB_CLOSED));
brave_shields_settings()->SetAutoShredMode(AutoShredMode::APP_EXIT, kTestUrl);
EXPECT_EQ(brave_shields_settings()->GetAutoShredMode(kTestUrl),
AutoShredMode::APP_EXIT);
// verify underlying AutoShredMode is updated
EXPECT_EQ(GetHostContentSettingsMap()->GetWebsiteSetting(
kTestUrl, GURL(),
brave_shields::AutoShredSetting::kContentSettingsType),
AutoShredDictFrom(AutoShredMode::APP_EXIT));
// verify other urls remain unchanged
EXPECT_EQ(
brave_shields_settings()->GetAutoShredMode(GURL("https://example.com")),
AutoShredMode::NEVER);
EXPECT_EQ(GetHostContentSettingsMap()->GetWebsiteSetting(
GURL("https://example.com"), GURL(),
brave_shields::AutoShredSetting::kContentSettingsType),
AutoShredDictFrom(AutoShredMode::NEVER));
}
TEST_F(BraveShieldsSettingsServiceTest, DefaultAutoShredMode) {
// explicitly set so we can verify this is unchanged by updating default
brave_shields_settings()->SetAutoShredMode(AutoShredMode::NEVER, kTestUrl);
// verify the initial default values
EXPECT_EQ(brave_shields_settings()->GetDefaultAutoShredMode(),
AutoShredMode::NEVER);
EXPECT_EQ(GetHostContentSettingsMap()->GetWebsiteSetting(
GURL(), GURL(),
brave_shields::AutoShredSetting::kContentSettingsType),
AutoShredDictFrom(AutoShredMode::NEVER));
brave_shields_settings()->SetDefaultAutoShredMode(
AutoShredMode::LAST_TAB_CLOSED);
EXPECT_EQ(brave_shields_settings()->GetDefaultAutoShredMode(),
AutoShredMode::LAST_TAB_CLOSED);
EXPECT_EQ(
brave_shields_settings()->GetAutoShredMode(GURL("https://example.com")),
AutoShredMode::LAST_TAB_CLOSED);
// verify underlying AutoShredMode is updated
EXPECT_EQ(GetHostContentSettingsMap()->GetWebsiteSetting(
GURL(), GURL(),
brave_shields::AutoShredSetting::kContentSettingsType),
AutoShredDictFrom(AutoShredMode::LAST_TAB_CLOSED));
// verify explict set auto shred mode unchanged
EXPECT_EQ(brave_shields_settings()->GetAutoShredMode(kTestUrl),
AutoShredMode::NEVER);
// verify underlying AutoShredMode is unchanged
EXPECT_EQ(GetHostContentSettingsMap()->GetWebsiteSetting(
kTestUrl, GURL(),
brave_shields::AutoShredSetting::kContentSettingsType),
AutoShredDictFrom(AutoShredMode::NEVER));
}
@@ -24,6 +24,7 @@ static_library("common") {
deps = [
"//base",
"//brave/components/brave_shields/core/common:mojom",
"//brave/components/webcompat/core/common",
"//components/content_settings/core/common",
"//net",
@@ -26,6 +26,7 @@ inline constexpr char kBraveShields[] = "braveShields";
inline constexpr char kBraveShieldsMetadata[] = "braveShieldsMetadata";
inline constexpr char kReferrers[] = "referrers";
inline constexpr char kCookies[] = "shieldsCookiesV3";
inline constexpr char kBraveAutoShred[] = "braveAutoShred";
// Prefs:
inline constexpr char kFacebookEmbeds[] = "fb-embeds";
@@ -42,6 +43,7 @@ inline constexpr auto kShieldsContentSettingsTypes =
ContentSettingsType::BRAVE_SHIELDS,
ContentSettingsType::BRAVE_REFERRERS,
ContentSettingsType::BRAVE_COOKIES,
ContentSettingsType::BRAVE_AUTO_SHRED,
});
using ShieldsContentSettingsTypes = decltype(kShieldsContentSettingsTypes);
@@ -60,6 +62,7 @@ inline constexpr auto kShieldsContentTypeNames =
{ContentSettingsType::BRAVE_SHIELDS_METADATA, kBraveShieldsMetadata},
{ContentSettingsType::BRAVE_REFERRERS, kReferrers},
{ContentSettingsType::BRAVE_COOKIES, kCookies},
{ContentSettingsType::BRAVE_AUTO_SHRED, kBraveAutoShred},
});
using ShieldsContentTypeNames = decltype(kShieldsContentTypeNames);
@@ -11,6 +11,7 @@
#include "base/types/cxx23_to_underlying.h"
#include "base/values.h"
#include "brave/components/brave_shields/core/common/brave_shield_constants.h"
#include "brave/components/brave_shields/core/common/shields_settings.mojom.h"
#include "components/content_settings/core/common/content_settings_types.h"
namespace brave_shields {
@@ -44,6 +45,22 @@ struct SettingTraits<ControlType> {
}
};
template <>
struct SettingTraits<mojom::AutoShredMode> {
static std::optional<mojom::AutoShredMode> From(
std::underlying_type_t<mojom::AutoShredMode> v) {
if (v >= static_cast<int>(mojom::AutoShredMode::NEVER) &&
v <= static_cast<int>(mojom::AutoShredMode::kMaxValue)) {
return static_cast<mojom::AutoShredMode>(v);
}
return std::nullopt;
}
static int To(mojom::AutoShredMode setting) {
return base::to_underlying(setting);
}
};
namespace internal {
const char* NotShieldContentTypeFailure();
}
@@ -107,6 +124,11 @@ using CosmeticFilteringSetting = traits::BraveShieldsSetting<
/*SettingType=*/ControlType,
/*default_value=*/ControlType::BLOCK_THIRD_PARTY>;
using AutoShredSetting = traits::BraveShieldsSetting<
/*content_settings_type=*/ContentSettingsType::BRAVE_AUTO_SHRED,
/*SettingType=*/mojom::AutoShredMode,
/*default_value=*/mojom::AutoShredMode::NEVER>;
} // namespace brave_shields
#endif // BRAVE_COMPONENTS_BRAVE_SHIELDS_CORE_COMMON_BRAVE_SHIELDS_SETTINGS_VALUES_H_
@@ -82,7 +82,8 @@ using ControlTypeAllShieldsSettingsValuesChecker =
ContentSettingsType::BRAVE_SHIELDS,
ContentSettingsType::BRAVE_SHIELDS_METADATA,
ContentSettingsType::BRAVE_REFERRERS,
ContentSettingsType::BRAVE_COOKIES>;
ContentSettingsType::BRAVE_COOKIES,
ContentSettingsType::BRAVE_AUTO_SHRED>;
TEST_F(ShieldsSettingsValuesTest, ControlTypeSettingTypeSuccess) {
ControlTypeAllShieldsSettingsValuesChecker checker;
@@ -45,3 +45,11 @@ enum HttpsUpgradeMode {
STANDARD_MODE,
DISABLED_MODE
};
// Do not change order of this enum. The order is relied upon for
// it's accompanying shield setting.
enum AutoShredMode {
NEVER = 0,
LAST_TAB_CLOSED,
APP_EXIT,
};
@@ -35,6 +35,12 @@ NS_SWIFT_NAME(BraveShieldsSettings)
NS_SWIFT_NAME(fingerprintMode(for:));
- (void)setFingerprintMode:(BraveShieldsFingerprintMode)fingerprintMode
forURL:(NSURL*)url;
@property(nonatomic) BraveShieldsAutoShredMode defaultAutoShredMode;
- (BraveShieldsAutoShredMode)autoShredModeForURL:(NSURL*)url
NS_SWIFT_NAME(autoShredMode(for:));
- (void)setAutoShredMode:(BraveShieldsAutoShredMode)autoShredMode
forURL:(NSURL*)url;
@end
#endif // BRAVE_COMPONENTS_BRAVE_SHIELDS_IOS_BROWSER_BRAVE_SHIELDS_SETTINGS_BRIDGE_H_
@@ -101,4 +101,27 @@
gurl);
}
- (BraveShieldsAutoShredMode)defaultAutoShredMode {
return static_cast<BraveShieldsAutoShredMode>(
_braveShieldsSettings->GetDefaultAutoShredMode());
}
- (BraveShieldsAutoShredMode)autoShredModeForURL:(NSURL*)url {
GURL gurl = net::GURLWithNSURL(url);
return static_cast<BraveShieldsAutoShredMode>(
_braveShieldsSettings->GetAutoShredMode(gurl));
}
- (void)setDefaultAutoShredMode:(BraveShieldsAutoShredMode)autoShredMode {
_braveShieldsSettings->SetDefaultAutoShredMode(
static_cast<brave_shields::mojom::AutoShredMode>(autoShredMode));
}
- (void)setAutoShredMode:(BraveShieldsAutoShredMode)autoShredMode
forURL:(NSURL*)url {
GURL gurl = net::GURLWithNSURL(url);
_braveShieldsSettings->SetAutoShredMode(
static_cast<brave_shields::mojom::AutoShredMode>(autoShredMode), gurl);
}
@end
@@ -655,6 +655,10 @@ TEST_F(BravePrefProviderTest, TestShieldsSettingsMigrationFromResourceIDs) {
CheckMigrationFromResourceIdentifierForDictionary(
brave_shields_dict, "www.brave.com,*", expected_last_modified,
expected_brave_com_settings_value);
} else if (content_type == ContentSettingsType::BRAVE_AUTO_SHRED) {
// BRAVE_AUTO_SHRED was added after the ResourceIdentifier migration
// and never existed in that old format, so we can skip validating it.
EXPECT_TRUE(brave_shields_dict.empty());
} else {
// All the other settings we changed them globally and in www.example.com.
CheckMigrationFromResourceIdentifierForDictionary(
@@ -26,6 +26,11 @@ class TestBraveShieldsSettings: BraveShieldsSettings {
var _fingerprintMode: ((URL) -> BraveShields.FingerprintMode)?
var _setFingerprintMode: ((BraveShields.FingerprintMode, URL) -> Void)?
var _defaultAutoShredMode: (() -> BraveShields.AutoShredMode)?
var _setDefaultAutoShredMode: ((BraveShields.AutoShredMode) -> Void)?
var _autoShredMode: ((URL) -> BraveShields.AutoShredMode)?
var _setAutoShredMode: ((BraveShields.AutoShredMode, URL) -> Void)?
// MARK: Brave ShieldsEnabled
func isBraveShieldsEnabled(for url: URL) -> Bool {
@@ -85,4 +90,21 @@ class TestBraveShieldsSettings: BraveShieldsSettings {
func setFingerprintMode(_ fingerprintMode: BraveShields.FingerprintMode, for url: URL!) {
_setFingerprintMode?(fingerprintMode, url)
}
// MARK: AutoShredMode
var defaultAutoShredMode: BraveShields.AutoShredMode {
get {
_defaultAutoShredMode?() ?? .never
}
set {
_setDefaultAutoShredMode?(newValue)
}
}
func autoShredMode(for url: URL) -> BraveShields.AutoShredMode {
return _autoShredMode?(url) ?? defaultAutoShredMode
}
func setAutoShredMode(_ fingerprintMode: BraveShields.AutoShredMode, for url: URL!) {
_setAutoShredMode?(fingerprintMode, url)
}
}