Add Speedreader admin policy (#30017)
This commit is contained in:
@@ -980,6 +980,7 @@ BraveContentBrowserClient::CreateURLLoaderThrottles(
|
||||
auto* speedreader_service =
|
||||
speedreader::SpeedreaderServiceFactory::GetForBrowserContext(
|
||||
browser_context);
|
||||
CHECK(speedreader_service);
|
||||
|
||||
auto producer =
|
||||
speedreader::SpeedreaderDistilledPageProducer::MaybeCreate(
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "brave/components/brave_vpn/common/buildflags/buildflags.h"
|
||||
#include "brave/components/constants/pref_names.h"
|
||||
#include "brave/components/ipfs/buildflags/buildflags.h"
|
||||
#include "brave/components/speedreader/common/buildflags/buildflags.h"
|
||||
#include "brave/components/tor/buildflags/buildflags.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/policy/core/browser/configuration_policy_handler.h"
|
||||
@@ -34,6 +35,10 @@
|
||||
#include "brave/components/ipfs/ipfs_prefs.h"
|
||||
#endif // BUILDFLAG(DEPRECATE_IPFS)
|
||||
|
||||
#if BUILDFLAG(ENABLE_SPEEDREADER)
|
||||
#include "brave/components/speedreader/speedreader_pref_names.h"
|
||||
#endif
|
||||
|
||||
namespace policy {
|
||||
|
||||
inline constexpr PolicyToPreferenceMapEntry kBraveSimplePolicyMap[] = {
|
||||
@@ -65,6 +70,10 @@ inline constexpr PolicyToPreferenceMapEntry kBraveSimplePolicyMap[] = {
|
||||
brave_news::prefs::kBraveNewsDisabledByPolicy, base::Value::Type::BOOLEAN},
|
||||
{policy::key::kBraveTalkDisabled, kBraveTalkDisabledByPolicy,
|
||||
base::Value::Type::BOOLEAN},
|
||||
#if BUILDFLAG(ENABLE_SPEEDREADER)
|
||||
{policy::key::kBraveSpeedreaderDisabled,
|
||||
speedreader::kSpeedreaderDisabledByPolicy, base::Value::Type::BOOLEAN},
|
||||
#endif
|
||||
#endif
|
||||
#if BUILDFLAG(DEPRECATE_IPFS)
|
||||
{policy::key::kIPFSEnabled, ipfs::prefs::kIPFSEnabledByPolicy,
|
||||
|
||||
@@ -76,7 +76,8 @@ function getPageVisibility () {
|
||||
// </if>
|
||||
content: alwaysTrueProxy,
|
||||
playlist: loadTimeData.getBoolean('isPlaylistAllowed'),
|
||||
speedreader: loadTimeData.getBoolean('isSpeedreaderFeatureEnabled'),
|
||||
speedreader: loadTimeData.getBoolean('isSpeedreaderFeatureEnabled') &&
|
||||
!loadTimeData.getBoolean('isSpeedreaderDisabledByPolicy'),
|
||||
}
|
||||
// Proxy so we can respond to any other property
|
||||
return new Proxy(staticProps, {
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
|
||||
#include "chrome/browser/profiles/incognito_helpers.h"
|
||||
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
||||
#include "components/user_prefs/user_prefs.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
|
||||
namespace speedreader {
|
||||
|
||||
@@ -49,6 +51,12 @@ SpeedreaderServiceFactory::BuildServiceInstanceForBrowserContext(
|
||||
if (!features::IsSpeedreaderEnabled()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Don't create service if disabled by policy
|
||||
if (speedreader::IsDisabledByPolicy(user_prefs::UserPrefs::Get(context))) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::make_unique<SpeedreaderService>(
|
||||
context, g_browser_process->local_state(),
|
||||
HostContentSettingsMapFactory::GetForProfile(context));
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "components/dom_distiller/content/browser/distillable_page_utils.h"
|
||||
#include "components/grit/brave_components_resources.h"
|
||||
#include "components/grit/brave_components_strings.h"
|
||||
#include "components/user_prefs/user_prefs.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "content/public/browser/navigation_handle.h"
|
||||
#include "content/public/browser/reload_type.h"
|
||||
@@ -94,6 +96,14 @@ void SpeedreaderTabHelper::MaybeCreateForWebContents(
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if speedreader is available (feature enabled and not disabled by
|
||||
// policy)
|
||||
auto* speedreader_service = SpeedreaderServiceFactory::GetForBrowserContext(
|
||||
contents->GetBrowserContext());
|
||||
if (!speedreader_service) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* rewriter_service =
|
||||
g_brave_browser_process->speedreader_rewriter_service();
|
||||
if (!rewriter_service) {
|
||||
@@ -168,6 +178,10 @@ bool SpeedreaderTabHelper::MaybeUpdateCachedState(
|
||||
return false;
|
||||
}
|
||||
auto* speedreader_service = GetSpeedreaderService();
|
||||
if (!speedreader_service) {
|
||||
SpeedreaderExtendedInfoHandler::ClearPersistedData(entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
const DistillState state =
|
||||
SpeedreaderExtendedInfoHandler::GetCachedMode(entry, speedreader_service);
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
|
||||
#if BUILDFLAG(ENABLE_SPEEDREADER)
|
||||
#include "brave/components/speedreader/common/features.h"
|
||||
#include "brave/components/speedreader/speedreader_pref_names.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
@@ -165,6 +166,9 @@ void BraveSettingsUI::AddResources(content::WebUIDataSource* html_source,
|
||||
html_source->AddBoolean(
|
||||
"isSpeedreaderFeatureEnabled",
|
||||
base::FeatureList::IsEnabled(speedreader::kSpeedreaderFeature));
|
||||
html_source->AddBoolean("isSpeedreaderDisabledByPolicy",
|
||||
profile->GetPrefs()->GetBoolean(
|
||||
speedreader::kSpeedreaderDisabledByPolicy));
|
||||
#endif
|
||||
html_source->AddBoolean(
|
||||
"isNativeBraveWalletFeatureEnabled",
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
caption: Disable Speedreader
|
||||
default: null
|
||||
desc: |-
|
||||
Disable Speedreader in Brave.
|
||||
|
||||
Speedreader is a feature that provides a clutter-free reading experience by automatically cleaning up articles and simplifying page layouts.
|
||||
|
||||
If this policy is set to true, Speedreader will always be disabled and all related UI elements will be hidden.
|
||||
|
||||
If this policy is set to false, Speedreader will always be enabled.
|
||||
|
||||
If you set this policy, users cannot change or override it.
|
||||
|
||||
If this policy is left unset, Speedreader will be enabled by default (subject to user preferences).
|
||||
example_value: true
|
||||
features:
|
||||
can_be_mandatory: true
|
||||
can_be_recommended: false
|
||||
dynamic_refresh: false
|
||||
per_profile: true
|
||||
items:
|
||||
- caption: Enable Speedreader
|
||||
value: false
|
||||
- caption: Disable Speedreader
|
||||
value: true
|
||||
- caption: Allow the user to decide
|
||||
value: null
|
||||
owners:
|
||||
- bbondy@brave.com
|
||||
- clifton@brave.com
|
||||
schema:
|
||||
type: boolean
|
||||
supported_on:
|
||||
- chrome.*:138-
|
||||
tags: []
|
||||
type: main
|
||||
@@ -17,3 +17,12 @@ In a nutshell, the steps for adding a new policy in Brave look like this:
|
||||
7. The group policy assets get output to `//out/<build_type_here>/brave_policy_templates.zip`. You can open this up and inspect the registry and adm/admx files. There is also a `policy_templates.zip` - that is the raw output before the script at `//brave/components/policy/pack_policy_templates.py` runs.
|
||||
|
||||
If rebuilding isn't picking up your policy, you can try to delete `//out/<build_type_here>/gen/components/policy/policy_constants.cc`. Rebuilding will trigger the rebuild for this file and your changes should be there.
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you're getting an error similar to:
|
||||
|
||||
> ../../brave/browser/policy/brave_simple_policy_map.h:75:19: error: no member named 'kBraveSpeedreaderDisabled' in namespace 'policy::key'; did you mean 'kBraveRewardsDisabled'?
|
||||
|
||||
It might be that the minimum Chromium version is not yet in use by Brave via the YAML's `supported_on`. In that case you will need to temporarily specify a lower version until Brave updates to the newer version.
|
||||
|
||||
@@ -10,6 +10,7 @@ _brave_policies = [
|
||||
"BraveSoftware/BraveRewardsDisabled.yaml",
|
||||
"BraveSoftware/BraveShieldsDisabledForUrls.yaml",
|
||||
"BraveSoftware/BraveShieldsEnabledForUrls.yaml",
|
||||
"BraveSoftware/BraveSpeedreaderDisabled.yaml",
|
||||
"BraveSoftware/BraveSyncUrl.yaml",
|
||||
"BraveSoftware/BraveTalkDisabled.yaml",
|
||||
"BraveSoftware/BraveVPNDisabled.yaml",
|
||||
|
||||
@@ -65,6 +65,7 @@ source_set("unit_tests") {
|
||||
sources = [
|
||||
"speedreader_metrics_unittest.cc",
|
||||
"speedreader_rewriter_unittest.cc",
|
||||
"speedreader_service_unittest.cc",
|
||||
"speedreader_util_unittest.cc",
|
||||
]
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@ inline constexpr char kSpeedreaderPrefTtsSpeed[] =
|
||||
inline constexpr char kSpeedreaderPageViewsStoragePref[] =
|
||||
"brave.speedreader.page_views";
|
||||
|
||||
// Used to enable/disable Speedreader via a policy.
|
||||
inline constexpr char kSpeedreaderDisabledByPolicy[] =
|
||||
"brave.speedreader.disabled_by_policy";
|
||||
|
||||
} // namespace speedreader
|
||||
|
||||
#endif // BRAVE_COMPONENTS_SPEEDREADER_SPEEDREADER_PREF_NAMES_H_
|
||||
|
||||
@@ -44,6 +44,10 @@ bool IsSpeedreaderEnabled() {
|
||||
|
||||
} // namespace features
|
||||
|
||||
bool IsDisabledByPolicy(PrefService* prefs) {
|
||||
return prefs->GetBoolean(kSpeedreaderDisabledByPolicy);
|
||||
}
|
||||
|
||||
SpeedreaderService::SpeedreaderService(content::BrowserContext* browser_context,
|
||||
PrefService* local_state,
|
||||
HostContentSettingsMap* content_rules)
|
||||
@@ -83,6 +87,7 @@ void SpeedreaderService::RegisterProfilePrefs(PrefRegistrySimple* registry) {
|
||||
registry->RegisterStringPref(kSpeedreaderPrefTtsVoice, "");
|
||||
registry->RegisterIntegerPref(kSpeedreaderPrefTtsSpeed,
|
||||
static_cast<int>(PlaybackSpeed::k100));
|
||||
registry->RegisterBooleanPref(kSpeedreaderDisabledByPolicy, false);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -99,7 +104,9 @@ void SpeedreaderService::RemoveObserver(Observer* observer) {
|
||||
}
|
||||
|
||||
bool SpeedreaderService::IsEnabledForAllSites() {
|
||||
return prefs_->GetBoolean(kSpeedreaderPrefEnabled);
|
||||
bool disabled_by_policy = speedreader::IsDisabledByPolicy(prefs_);
|
||||
bool enabled_pref = prefs_->GetBoolean(kSpeedreaderPrefEnabled);
|
||||
return !disabled_by_policy && enabled_pref;
|
||||
}
|
||||
|
||||
ContentSetting SpeedreaderService::GetEnabledForSiteSetting(const GURL& url) {
|
||||
|
||||
@@ -31,6 +31,9 @@ namespace features {
|
||||
bool IsSpeedreaderEnabled();
|
||||
}
|
||||
|
||||
// Returns true if Speedreader is disabled by policy.
|
||||
bool IsDisabledByPolicy(PrefService* prefs);
|
||||
|
||||
class SpeedreaderService : public KeyedService {
|
||||
public:
|
||||
class Observer : public base::CheckedObserver {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2025 The Brave Authors. All rights reserved.
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "brave/components/speedreader/speedreader_service.h"
|
||||
|
||||
#include "base/test/task_environment.h"
|
||||
#include "brave/components/speedreader/speedreader_pref_names.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
#include "components/sync_preferences/testing_pref_service_syncable.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace speedreader {
|
||||
|
||||
class SpeedreaderPolicyTest : public testing::Test {
|
||||
public:
|
||||
SpeedreaderPolicyTest() {
|
||||
SpeedreaderService::RegisterProfilePrefs(pref_service_.registry());
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetSpeedreaderDisabledByPolicy(bool value) {
|
||||
pref_service_.SetManagedPref(kSpeedreaderDisabledByPolicy,
|
||||
base::Value(value));
|
||||
}
|
||||
|
||||
sync_preferences::TestingPrefServiceSyncable pref_service_;
|
||||
};
|
||||
|
||||
TEST_F(SpeedreaderPolicyTest, PolicyDisablesSpeedreader) {
|
||||
// Initially, policy should not be disabled
|
||||
EXPECT_FALSE(pref_service_.GetBoolean(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_FALSE(pref_service_.IsManagedPreference(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_FALSE(IsDisabledByPolicy(&pref_service_));
|
||||
|
||||
// Set policy to disable Speedreader
|
||||
SetSpeedreaderDisabledByPolicy(true);
|
||||
|
||||
// Test that the policy preference is set correctly
|
||||
EXPECT_TRUE(pref_service_.FindPreference(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_TRUE(pref_service_.IsManagedPreference(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_TRUE(pref_service_.GetBoolean(kSpeedreaderDisabledByPolicy));
|
||||
|
||||
// Test that IsDisabledByPolicy function works
|
||||
EXPECT_TRUE(IsDisabledByPolicy(&pref_service_));
|
||||
}
|
||||
|
||||
TEST_F(SpeedreaderPolicyTest, PolicyEnablesSpeedreader) {
|
||||
// Set policy to explicitly enable Speedreader (policy value false = not
|
||||
// disabled)
|
||||
SetSpeedreaderDisabledByPolicy(false);
|
||||
|
||||
// Test that the policy preference is set correctly
|
||||
EXPECT_TRUE(pref_service_.FindPreference(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_TRUE(pref_service_.IsManagedPreference(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_FALSE(pref_service_.GetBoolean(kSpeedreaderDisabledByPolicy));
|
||||
|
||||
// Test that IsDisabledByPolicy function works
|
||||
EXPECT_FALSE(IsDisabledByPolicy(&pref_service_));
|
||||
}
|
||||
|
||||
TEST_F(SpeedreaderPolicyTest, DefaultValueWhenNotManaged) {
|
||||
// When not managed by policy, should be false by default
|
||||
EXPECT_FALSE(pref_service_.GetBoolean(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_FALSE(pref_service_.IsManagedPreference(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_FALSE(IsDisabledByPolicy(&pref_service_));
|
||||
}
|
||||
|
||||
TEST_F(SpeedreaderPolicyTest, PolicyChangesAreReflected) {
|
||||
// Start with policy allowing speedreader
|
||||
SetSpeedreaderDisabledByPolicy(false);
|
||||
EXPECT_FALSE(IsDisabledByPolicy(&pref_service_));
|
||||
|
||||
// Change policy to disable speedreader
|
||||
SetSpeedreaderDisabledByPolicy(true);
|
||||
EXPECT_TRUE(IsDisabledByPolicy(&pref_service_));
|
||||
|
||||
// Change back to allowing speedreader
|
||||
SetSpeedreaderDisabledByPolicy(false);
|
||||
EXPECT_FALSE(IsDisabledByPolicy(&pref_service_));
|
||||
}
|
||||
|
||||
TEST_F(SpeedreaderPolicyTest, PolicyWorksWithDefaultsWrite) {
|
||||
// This simulates the behavior when using "defaults write" command on macOS
|
||||
// where the preference is set but not marked as managed
|
||||
|
||||
// Manually set the preference value without using SetManagedPref
|
||||
pref_service_.SetBoolean(kSpeedreaderDisabledByPolicy, true);
|
||||
|
||||
// Verify the preference is set but not marked as managed
|
||||
EXPECT_TRUE(pref_service_.GetBoolean(kSpeedreaderDisabledByPolicy));
|
||||
EXPECT_FALSE(pref_service_.IsManagedPreference(kSpeedreaderDisabledByPolicy));
|
||||
|
||||
// IsDisabledByPolicy should still return true since we just check the
|
||||
// preference value
|
||||
EXPECT_TRUE(IsDisabledByPolicy(&pref_service_));
|
||||
}
|
||||
|
||||
} // namespace speedreader
|
||||
Reference in New Issue
Block a user