Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Speedreader metrics #27874

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions browser/brave_local_state_prefs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "brave/components/p3a/p3a_service.h"
#include "brave/components/p3a/star_randomness_meta.h"
#include "brave/components/skus/browser/skus_utils.h"
#include "brave/components/speedreader/speedreader_service.h"
#include "brave/components/tor/buildflags/buildflags.h"
#include "brave/components/web_discovery/buildflags/buildflags.h"
#include "build/build_config.h"
Expand Down Expand Up @@ -179,6 +180,7 @@ void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE)
web_discovery::WebDiscoveryService::RegisterLocalStatePrefs(registry);
#endif
speedreader::SpeedreaderService::RegisterLocalStatePrefs(registry);
}

} // namespace brave
4 changes: 3 additions & 1 deletion browser/speedreader/speedreader_service_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "base/no_destructor.h"
#include "brave/components/speedreader/speedreader_service.h"
#include "chrome/browser/browser_process.h"
#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"
Expand Down Expand Up @@ -49,7 +50,8 @@ SpeedreaderServiceFactory::BuildServiceInstanceForBrowserContext(
return {};
}
return std::make_unique<SpeedreaderService>(
context, HostContentSettingsMapFactory::GetForProfile(context));
g_browser_process->local_state(), context,
HostContentSettingsMapFactory::GetForProfile(context));
}

bool SpeedreaderServiceFactory::ServiceIsCreatedWithBrowserContext() const {
Expand Down
2 changes: 2 additions & 0 deletions components/p3a/metric_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ inline constexpr auto kCollectedSlowHistograms =
{"Brave.Rewards.TipsSent.2", MetricConfig{.ephemeral = true}},
{"Brave.Search.SearchSuggest", {}},
{"Brave.Shields.ForgetFirstParty", {}},
{"Brave.Speedreader.EnabledSites", {}},
{"Brave.Speedreader.PageViews", MetricConfig{.ephemeral = true}},
{"Brave.Sync.EnabledTypes", {}},
{"Brave.Sync.SyncedObjectsCount.2", {}},
{"Brave.Today.ChannelCount.2", MetricConfig{.ephemeral = true}},
Expand Down
28 changes: 28 additions & 0 deletions components/speedreader/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ static_library("speedreader") {
"speedreader_distilled_page_producer.h",
"speedreader_extended_info_handler.cc",
"speedreader_extended_info_handler.h",
"speedreader_metrics.cc",
"speedreader_metrics.h",
"speedreader_pref_names.h",
"speedreader_rewriter_service.cc",
"speedreader_rewriter_service.h",
Expand All @@ -36,6 +38,7 @@ static_library("speedreader") {
deps = [
"rust/ffi",
"//brave/components/body_sniffer",
"//brave/components/p3a_utils",
"//brave/components/resources",
"//brave/components/resources:static_resources_grit",
"//brave/components/speedreader/common:mojom",
Expand All @@ -55,3 +58,28 @@ static_library("speedreader") {
"//url",
]
}

source_set("unit_tests") {
testonly = true

sources = [
"speedreader_metrics_unittest.cc",
"speedreader_rewriter_unittest.cc",
"speedreader_util_unittest.cc",
]

deps = [
":speedreader",
"//base",
"//base/test:test_support",
"//brave/components/constants",
"//brave/components/p3a_utils",
"//brave/components/time_period_storage",
"//components/content_settings/core/browser",
"//components/content_settings/core/common",
"//components/prefs:test_support",
"//components/sync_preferences:test_support",
"//testing/gtest",
"//url",
]
}
92 changes: 92 additions & 0 deletions components/speedreader/speedreader_metrics.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* 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_metrics.h"

#include "base/metrics/histogram_macros.h"
#include "brave/components/p3a_utils/bucket.h"
#include "brave/components/speedreader/speedreader_pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"

namespace speedreader {

namespace {

constexpr int kPageViewsBuckets[] = {5, 10, 20, 30};

constexpr base::TimeDelta kUpdateInterval = base::Days(1);

enum class EnabledSitesMetricValue {
kNone = 0, // No sites enabled
kOne = 1, // 1 site enabled
kMultiple = 2, // 2+ sites enabled
kAll = 3, // All sites enabled
kMaxValue = kAll
};

} // namespace

SpeedreaderMetrics::SpeedreaderMetrics(
PrefService* local_state,
HostContentSettingsMap* host_content_settings_map,
bool is_enabled_for_all_sites)
: page_views_storage_(local_state, kSpeedreaderPageViewsStoragePref),
host_content_settings_map_(host_content_settings_map),
local_state_(local_state) {
ReportPageViews();
UpdateEnabledSitesMetric(is_enabled_for_all_sites);
}

SpeedreaderMetrics::~SpeedreaderMetrics() = default;

// static
void SpeedreaderMetrics::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(kSpeedreaderPageViewsStoragePref);
}

void SpeedreaderMetrics::RecordPageView() {
page_views_storage_.AddDelta(1);
ReportPageViews();
}

void SpeedreaderMetrics::UpdateEnabledSitesMetric(
bool is_enabled_for_all_sites) {
EnabledSitesMetricValue value = EnabledSitesMetricValue::kNone;

if (is_enabled_for_all_sites) {
value = EnabledSitesMetricValue::kAll;
} else if (host_content_settings_map_) {
auto settings = host_content_settings_map_->GetSettingsForOneType(
ContentSettingsType::BRAVE_SPEEDREADER);
size_t enabled_sites_count =
std::ranges::count_if(settings, [](const auto& setting) {
return setting.GetContentSetting() == CONTENT_SETTING_ALLOW;
});
if (enabled_sites_count == 1) {
value = EnabledSitesMetricValue::kOne;
} else if (enabled_sites_count > 1) {
value = EnabledSitesMetricValue::kMultiple;
}
}

UMA_HISTOGRAM_ENUMERATION(kSpeedreaderEnabledSitesHistogramName, value);
}

void SpeedreaderMetrics::ReportPageViews() {
int page_views = page_views_storage_.GetMonthlySum();
if (page_views > 0) {
p3a_utils::RecordToHistogramBucket(kSpeedreaderPageViewsHistogramName,
kPageViewsBuckets, page_views);
}

update_timer_.Start(FROM_HERE, base::Time::Now() + kUpdateInterval, this,
&SpeedreaderMetrics::ReportPageViews);
}

} // namespace speedreader
51 changes: 51 additions & 0 deletions components/speedreader/speedreader_metrics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* 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/. */

#ifndef BRAVE_COMPONENTS_SPEEDREADER_SPEEDREADER_METRICS_H_
#define BRAVE_COMPONENTS_SPEEDREADER_SPEEDREADER_METRICS_H_

#include "base/timer/wall_clock_timer.h"
#include "brave/components/time_period_storage/monthly_storage.h"

class PrefRegistrySimple;
class PrefService;
class HostContentSettingsMap;

namespace speedreader {

inline constexpr char kSpeedreaderPageViewsHistogramName[] =
"Brave.Speedreader.PageViews";
inline constexpr char kSpeedreaderEnabledSitesHistogramName[] =
"Brave.Speedreader.EnabledSites";

class SpeedreaderMetrics {
public:
SpeedreaderMetrics(PrefService* local_state,
HostContentSettingsMap* host_content_settings_map,
bool is_enabled_for_all_sites);
~SpeedreaderMetrics();

SpeedreaderMetrics(const SpeedreaderMetrics&) = delete;
SpeedreaderMetrics& operator=(const SpeedreaderMetrics&) = delete;

static void RegisterPrefs(PrefRegistrySimple* registry);

void RecordPageView();

void UpdateEnabledSitesMetric(bool is_enabled_for_all_sites);

private:
void ReportPageViews();

MonthlyStorage page_views_storage_;
raw_ptr<HostContentSettingsMap> host_content_settings_map_;
raw_ptr<PrefService> local_state_;

base::WallClockTimer update_timer_;
};

} // namespace speedreader

#endif // BRAVE_COMPONENTS_SPEEDREADER_SPEEDREADER_METRICS_H_
100 changes: 100 additions & 0 deletions components/speedreader/speedreader_metrics_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/* 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_metrics.h"

#include <memory>

#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace speedreader {

class SpeedreaderMetricsTest : public testing::Test {
public:
SpeedreaderMetricsTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}

void SetUp() override {
SpeedreaderMetrics::RegisterPrefs(local_state_.registry());
HostContentSettingsMap::RegisterProfilePrefs(profile_prefs_.registry());

host_content_settings_map_ =
new HostContentSettingsMap(&profile_prefs_, /*is_off_the_record*/ false,
/*store_last_modified*/ false,
/*restore_session*/ false,
/*should_record_metrics*/ false);

metrics_ = std::make_unique<SpeedreaderMetrics>(
&local_state_, host_content_settings_map_.get(), false);
}

void TearDown() override { host_content_settings_map_->ShutdownOnUIThread(); }

protected:
base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple local_state_;
sync_preferences::TestingPrefServiceSyncable profile_prefs_;
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
std::unique_ptr<SpeedreaderMetrics> metrics_;
base::HistogramTester histogram_tester_;
};

TEST_F(SpeedreaderMetricsTest, RecordPageViews) {
for (int i = 0; i < 5; i++) {
metrics_->RecordPageView();
}

histogram_tester_.ExpectUniqueSample(kSpeedreaderPageViewsHistogramName, 0,
5);

for (int i = 0; i < 5; i++) {
metrics_->RecordPageView();
}

histogram_tester_.ExpectBucketCount(kSpeedreaderPageViewsHistogramName, 1, 5);
histogram_tester_.ExpectTotalCount(kSpeedreaderPageViewsHistogramName, 10);

task_environment_.FastForwardBy(base::Days(45));

histogram_tester_.ExpectBucketCount(kSpeedreaderPageViewsHistogramName, 1,
34);
histogram_tester_.ExpectTotalCount(kSpeedreaderPageViewsHistogramName, 39);
}

TEST_F(SpeedreaderMetricsTest, EnabledSitesMetric) {
histogram_tester_.ExpectUniqueSample(kSpeedreaderEnabledSitesHistogramName, 0,
1);

ContentSettingsPattern pattern =
ContentSettingsPattern::FromString("*://example.com/*");
host_content_settings_map_->SetContentSettingCustomScope(
pattern, ContentSettingsPattern::Wildcard(),
ContentSettingsType::BRAVE_SPEEDREADER, CONTENT_SETTING_ALLOW);

metrics_->UpdateEnabledSitesMetric(false);
histogram_tester_.ExpectBucketCount(kSpeedreaderEnabledSitesHistogramName, 1,
1);

pattern = ContentSettingsPattern::FromString("*://brave.com/*");
host_content_settings_map_->SetContentSettingCustomScope(
pattern, ContentSettingsPattern::Wildcard(),
ContentSettingsType::BRAVE_SPEEDREADER, CONTENT_SETTING_ALLOW);

metrics_->UpdateEnabledSitesMetric(false);
histogram_tester_.ExpectBucketCount(kSpeedreaderEnabledSitesHistogramName, 2,
1);

metrics_->UpdateEnabledSitesMetric(true);
histogram_tester_.ExpectBucketCount(kSpeedreaderEnabledSitesHistogramName, 3,
1);
}

} // namespace speedreader
3 changes: 3 additions & 0 deletions components/speedreader/speedreader_pref_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ inline constexpr char kSpeedreaderPrefTtsVoice[] =
inline constexpr char kSpeedreaderPrefTtsSpeed[] =
"brave.speedreader.tts_speed";

inline constexpr char kSpeedreaderPageViewsStoragePref[] =
"brave.speedreader.page_views";

} // namespace speedreader

#endif // BRAVE_COMPONENTS_SPEEDREADER_SPEEDREADER_PREF_NAMES_H_
17 changes: 15 additions & 2 deletions components/speedreader/speedreader_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ bool IsSpeedreaderEnabled() {

} // namespace features

SpeedreaderService::SpeedreaderService(content::BrowserContext* browser_context,
SpeedreaderService::SpeedreaderService(PrefService* local_state,
content::BrowserContext* browser_context,
HostContentSettingsMap* content_rules)
: browser_context_(browser_context),
content_rules_(content_rules),
prefs_(user_prefs::UserPrefs::Get(browser_context_)) {
prefs_(user_prefs::UserPrefs::Get(browser_context_)),
metrics_(local_state, content_rules_, IsEnabledForAllSites()) {
DCHECK(features::IsSpeedreaderEnabled());
}

Expand Down Expand Up @@ -81,6 +83,11 @@ void SpeedreaderService::RegisterProfilePrefs(PrefRegistrySimple* registry) {
static_cast<int>(PlaybackSpeed::k100));
}

// static
void SpeedreaderService::RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
SpeedreaderMetrics::RegisterPrefs(registry);
}

void SpeedreaderService::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
Expand Down Expand Up @@ -164,6 +171,8 @@ void SpeedreaderService::EnableForAllSites(bool enabled) {
for (auto& o : observers_) {
o.OnAllSitesEnableSettingChanged(enabled);
}

metrics_.UpdateEnabledSitesMetric(enabled);
}

void SpeedreaderService::EnableForSite(const GURL& url, bool enabled) {
Expand All @@ -188,6 +197,8 @@ void SpeedreaderService::EnableForSite(const GURL& url, bool enabled) {
content_rules_->SetContentSettingCustomScope(
pattern, ContentSettingsPattern::Wildcard(),
ContentSettingsType::BRAVE_SPEEDREADER, setting);

metrics_.UpdateEnabledSitesMetric(IsEnabledForAllSites());
}

void SpeedreaderService::EnableForSite(content::WebContents* contents,
Expand All @@ -198,6 +209,8 @@ void SpeedreaderService::EnableForSite(content::WebContents* contents,
o.OnSiteEnableSettingChanged(contents, enabled);
}
}

metrics_.UpdateEnabledSitesMetric(IsEnabledForAllSites());
}

void SpeedreaderService::SetAppearanceSettings(
Expand Down
Loading
Loading