diff --git a/android/java/org/chromium/base/BraveFeatureList.java b/android/java/org/chromium/base/BraveFeatureList.java index eef25bb0ddb..f850435e94d 100644 --- a/android/java/org/chromium/base/BraveFeatureList.java +++ b/android/java/org/chromium/base/BraveFeatureList.java @@ -31,6 +31,6 @@ public abstract class BraveFeatureList { public static final String AI_CHAT = "AIChat"; public static final String BRAVE_SHOW_STRICT_FINGERPRINTING_MODE = "BraveShowStrictFingerprintingMode"; - public static final String BRAVE_ZERO_DAY_FLAG_ANDROID = "BraveZeroDayFlagAndroid"; + public static final String BRAVE_DAY_ZERO_EXPERIMENT = "BraveDayZeroExperiment"; public static final String BRAVE_FALLBACK_DOH_PROVIDER = "BraveFallbackDoHProvider"; } diff --git a/browser/about_flags.cc b/browser/about_flags.cc index 2989c86f0cb..238c44b2fe6 100644 --- a/browser/about_flags.cc +++ b/browser/about_flags.cc @@ -372,18 +372,9 @@ kOsAndroid, \ FEATURE_VALUE_TYPE(safe_browsing::features::kBraveAndroidSafeBrowsing), \ }) -#define BRAVE_ZERO_DAY_FLAG_ANDROID \ - EXPAND_FEATURE_ENTRIES({ \ - "brave-zero-day-flag-android", \ - "ZeroDayFlag flag for product test", \ - "This flag will be set through griffin to perform product testing", \ - kOsAndroid, \ - FEATURE_VALUE_TYPE(preferences::features::kBraveZeroDayFlagAndroid), \ - }) #else #define BRAVE_BACKGROUND_VIDEO_PLAYBACK_ANDROID #define BRAVE_SAFE_BROWSING_ANDROID -#define BRAVE_ZERO_DAY_FLAG_ANDROID #endif // BUILDFLAG(IS_ANDROID) #if !BUILDFLAG(IS_ANDROID) @@ -992,7 +983,6 @@ BRAVE_COMMANDS_FEATURE_ENTRIES \ BRAVE_BACKGROUND_VIDEO_PLAYBACK_ANDROID \ BRAVE_SAFE_BROWSING_ANDROID \ - BRAVE_ZERO_DAY_FLAG_ANDROID \ BRAVE_CHANGE_ACTIVE_TAB_ON_SCROLL_EVENT_FEATURE_ENTRIES \ BRAVE_TABS_FEATURE_ENTRIES \ BRAVE_AI_CHAT \ diff --git a/browser/android/preferences/features.cc b/browser/android/preferences/features.cc index 0bad2e5e7f9..66ab0f82034 100644 --- a/browser/android/preferences/features.cc +++ b/browser/android/preferences/features.cc @@ -15,9 +15,5 @@ BASE_FEATURE(kBraveBackgroundVideoPlayback, "BraveBackgroundVideoPlayback", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kBraveZeroDayFlagAndroid, - "BraveZeroDayFlagAndroid", - base::FEATURE_DISABLED_BY_DEFAULT); - } // namespace features } // namespace preferences diff --git a/browser/android/preferences/features.h b/browser/android/preferences/features.h index 14a767da3fd..d877482a016 100644 --- a/browser/android/preferences/features.h +++ b/browser/android/preferences/features.h @@ -12,7 +12,6 @@ namespace preferences { namespace features { BASE_DECLARE_FEATURE(kBraveBackgroundVideoPlayback); -BASE_DECLARE_FEATURE(kBraveZeroDayFlagAndroid); } // namespace features } // namespace preferences diff --git a/browser/brave_browser_features.cc b/browser/brave_browser_features.cc index bc73aa2700f..136d8bb049f 100644 --- a/browser/brave_browser_features.cc +++ b/browser/brave_browser_features.cc @@ -35,4 +35,10 @@ BASE_FEATURE(kBraveWebViewRoundedCorners, "brave-web-view-rounded-corners", base::FEATURE_DISABLED_BY_DEFAULT); +// Enable "day zero" experiment modifications, for potential user +// retention improvements. +BASE_FEATURE(kBraveDayZeroExperiment, + "BraveDayZeroExperiment", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace features diff --git a/browser/brave_browser_features.h b/browser/brave_browser_features.h index c1264e5e58d..fef6b6587ea 100644 --- a/browser/brave_browser_features.h +++ b/browser/brave_browser_features.h @@ -14,7 +14,7 @@ BASE_DECLARE_FEATURE(kBraveCleanupSessionCookiesOnSessionRestore); BASE_DECLARE_FEATURE(kBraveCopyCleanLinkByDefault); BASE_DECLARE_FEATURE(kBraveOverrideDownloadDangerLevel); BASE_DECLARE_FEATURE(kBraveWebViewRoundedCorners); -BASE_DECLARE_FEATURE(kBraveZeroDayFlagAndroid); +BASE_DECLARE_FEATURE(kBraveDayZeroExperiment); } // namespace features diff --git a/browser/brave_stats/brave_stats_updater.cc b/browser/brave_stats/brave_stats_updater.cc index 876ce68e0cf..0f826ca1d04 100644 --- a/browser/brave_stats/brave_stats_updater.cc +++ b/browser/brave_stats/brave_stats_updater.cc @@ -12,8 +12,10 @@ #include "base/command_line.h" #include "base/metrics/histogram_macros.h" #include "base/system/sys_info.h" +#include "brave/browser/brave_browser_features.h" #include "brave/browser/brave_stats/brave_stats_updater_params.h" #include "brave/browser/brave_stats/buildflags.h" +#include "brave/browser/brave_stats/first_run_util.h" #include "brave/browser/brave_stats/switches.h" #include "brave/common/brave_channel_info.h" #include "brave/components/brave_ads/core/public/prefs/pref_names.h" @@ -26,6 +28,7 @@ #include "brave/components/rpill/common/rpill.h" #include "brave/components/version_info/version_info.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/channel_info.h" @@ -107,7 +110,10 @@ BraveStatsUpdater::BraveStatsUpdater(PrefService* pref_service, } general_browser_usage_p3a_ = - std::make_unique(pref_service); + std::make_unique( + pref_service, + base::FeatureList::IsEnabled(features::kBraveDayZeroExperiment), + first_run::IsChromeFirstRun(), GetFirstRunTime(pref_service)); if (profile_manager != nullptr) { g_browser_process->profile_manager()->AddObserver(this); diff --git a/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc b/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc index 68a2628cbd8..3b5d56ea33f 100644 --- a/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc @@ -37,7 +37,6 @@ &brave_wallet::features::kNativeBraveWalletFeature, \ &playlist::features::kPlaylist, \ &preferences::features::kBraveBackgroundVideoPlayback, \ - &preferences::features::kBraveZeroDayFlagAndroid, \ &request_otr::features::kBraveRequestOTRTab, \ &safe_browsing::features::kBraveAndroidSafeBrowsing, \ &speedreader::kSpeedreaderFeature, \ diff --git a/components/misc_metrics/general_browser_usage.cc b/components/misc_metrics/general_browser_usage.cc index c2c7e820d90..dc024058dac 100644 --- a/components/misc_metrics/general_browser_usage.cc +++ b/components/misc_metrics/general_browser_usage.cc @@ -6,6 +6,7 @@ #include "brave/components/misc_metrics/general_browser_usage.h" #include "base/metrics/histogram_macros.h" +#include "base/time/time.h" #include "brave/components/misc_metrics/pref_names.h" #include "brave/components/p3a_utils/bucket.h" #include "brave/components/time_period_storage/iso_weekly_storage.h" @@ -24,9 +25,23 @@ constexpr int kProfileCountBuckets[] = {0, 1, 2, 3, 5}; } // namespace -GeneralBrowserUsage::GeneralBrowserUsage(PrefService* local_state) { +GeneralBrowserUsage::GeneralBrowserUsage(PrefService* local_state, + bool day_zero_experiment_enabled, + bool is_first_run, + base::Time first_run_time) + : local_state_(local_state), first_run_time_(first_run_time) { usage_storage_ = std::make_unique( local_state, kMiscMetricsBrowserUsageList); + + if (is_first_run) { + if (day_zero_experiment_enabled) { + local_state->SetBoolean(kMiscMetricsDayZeroAtInstall, true); + } + if (first_run_time.is_null()) { + first_run_time_ = base::Time::Now(); + } + } + Update(); } @@ -34,6 +49,7 @@ GeneralBrowserUsage::~GeneralBrowserUsage() = default; void GeneralBrowserUsage::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterListPref(kMiscMetricsBrowserUsageList); + registry->RegisterBooleanPref(kMiscMetricsDayZeroAtInstall, false); } void GeneralBrowserUsage::ReportWeeklyUse() { @@ -42,6 +58,20 @@ void GeneralBrowserUsage::ReportWeeklyUse() { usage_storage_->GetLastISOWeekSum(), 8); } +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) +void GeneralBrowserUsage::ReportInstallTime() { + int days_since_install = (base::Time::Now() - first_run_time_).InDays(); + if (days_since_install < 0 || days_since_install > 30) { + return; + } + const char* histogram_name = + local_state_->GetBoolean(kMiscMetricsDayZeroAtInstall) + ? kDayZeroOnInstallTime + : kDayZeroOffInstallTime; + base::UmaHistogramExactLinear(histogram_name, days_since_install, 31); +} +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) + void GeneralBrowserUsage::ReportProfileCount(size_t count) { #if !BUILDFLAG(IS_ANDROID) p3a_utils::RecordToHistogramBucket(kProfileCountHistogramName, @@ -56,6 +86,9 @@ void GeneralBrowserUsage::SetUpUpdateTimer() { void GeneralBrowserUsage::Update() { ReportWeeklyUse(); +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) + ReportInstallTime(); +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) SetUpUpdateTimer(); } diff --git a/components/misc_metrics/general_browser_usage.h b/components/misc_metrics/general_browser_usage.h index 353e69e007a..70669d8d8a6 100644 --- a/components/misc_metrics/general_browser_usage.h +++ b/components/misc_metrics/general_browser_usage.h @@ -8,6 +8,7 @@ #include +#include "base/memory/raw_ptr.h" #include "base/timer/wall_clock_timer.h" class PrefRegistrySimple; @@ -19,9 +20,18 @@ namespace misc_metrics { inline constexpr char kWeeklyUseHistogramName[] = "Brave.Core.WeeklyUsage"; inline constexpr char kProfileCountHistogramName[] = "Brave.Core.ProfileCount"; +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) +inline constexpr char kDayZeroOnInstallTime[] = "Brave.DayZero.On.InstallTime"; +inline constexpr char kDayZeroOffInstallTime[] = + "Brave.DayZero.Off.InstallTime"; +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) + class GeneralBrowserUsage { public: - explicit GeneralBrowserUsage(PrefService* local_state); + GeneralBrowserUsage(PrefService* local_state, + bool day_zero_experiment_enabled, + bool is_first_run, + base::Time first_run_time); ~GeneralBrowserUsage(); GeneralBrowserUsage(const GeneralBrowserUsage&) = delete; @@ -33,11 +43,16 @@ class GeneralBrowserUsage { private: void ReportWeeklyUse(); +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) + void ReportInstallTime(); +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) void SetUpUpdateTimer(); void Update(); + raw_ptr local_state_; + base::Time first_run_time_; std::unique_ptr usage_storage_; base::WallClockTimer report_timer_; diff --git a/components/misc_metrics/general_browser_usage_unittest.cc b/components/misc_metrics/general_browser_usage_unittest.cc index 422a1cb0eb4..8a649602e6e 100644 --- a/components/misc_metrics/general_browser_usage_unittest.cc +++ b/components/misc_metrics/general_browser_usage_unittest.cc @@ -33,12 +33,17 @@ class GeneralBrowserUsageUnitTest : public testing::Test { days_until_monday = 1; } task_environment_.AdvanceClock(base::Days(days_until_monday)); - - general_browser_usage_ = - std::make_unique(&local_state_); } protected: + void SetUpUsage(bool day_zero_experiment_enabled, + bool is_first_run, + base::Time first_run_time) { + general_browser_usage_ = std::make_unique( + &local_state_, day_zero_experiment_enabled, is_first_run, + first_run_time); + } + content::BrowserTaskEnvironment task_environment_; TestingPrefServiceSimple local_state_; base::HistogramTester histogram_tester_; @@ -46,6 +51,8 @@ class GeneralBrowserUsageUnitTest : public testing::Test { }; TEST_F(GeneralBrowserUsageUnitTest, WeeklyUsage) { + SetUpUsage(false, true, base::Time::Now()); + histogram_tester_.ExpectUniqueSample(kWeeklyUseHistogramName, 0, 1); task_environment_.FastForwardBy(base::Days(1)); @@ -61,6 +68,8 @@ TEST_F(GeneralBrowserUsageUnitTest, WeeklyUsage) { #if !BUILDFLAG(IS_ANDROID) TEST_F(GeneralBrowserUsageUnitTest, ProfileCount) { + SetUpUsage(false, true, base::Time::Now()); + histogram_tester_.ExpectTotalCount(kProfileCountHistogramName, 0); general_browser_usage_->ReportProfileCount(1); @@ -73,4 +82,50 @@ TEST_F(GeneralBrowserUsageUnitTest, ProfileCount) { } #endif // !BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) +TEST_F(GeneralBrowserUsageUnitTest, InstallTimeOff) { + base::Time install_time = base::Time::Now(); + SetUpUsage(false, true, install_time); + + histogram_tester_.ExpectUniqueSample(kDayZeroOffInstallTime, 0, 1); + + task_environment_.FastForwardBy(base::Days(15)); + + histogram_tester_.ExpectBucketCount(kDayZeroOffInstallTime, 15, 1); + histogram_tester_.ExpectTotalCount(kDayZeroOnInstallTime, 0); + + SetUpUsage(true, false, install_time); + // Ensure histogram name does not change if "day zero" is enabled + // after install; we only want to report the "day zero on" metric + // if it was enabled at install time. + histogram_tester_.ExpectBucketCount(kDayZeroOffInstallTime, 15, 2); + histogram_tester_.ExpectTotalCount(kDayZeroOnInstallTime, 0); + + task_environment_.FastForwardBy(base::Days(15)); + histogram_tester_.ExpectBucketCount(kDayZeroOffInstallTime, 30, 1); + + // Ensure there are no more reports past 30 days + task_environment_.FastForwardBy(base::Days(5)); + + histogram_tester_.ExpectTotalCount(kDayZeroOffInstallTime, 32); + histogram_tester_.ExpectTotalCount(kDayZeroOnInstallTime, 0); +} + +TEST_F(GeneralBrowserUsageUnitTest, InstallTimeOn) { + base::Time install_time = base::Time::Now(); + SetUpUsage(true, true, install_time); + + histogram_tester_.ExpectUniqueSample(kDayZeroOnInstallTime, 0, 1); + + task_environment_.FastForwardBy(base::Days(15)); + + histogram_tester_.ExpectBucketCount(kDayZeroOnInstallTime, 15, 1); + histogram_tester_.ExpectTotalCount(kDayZeroOffInstallTime, 0); + + SetUpUsage(false, false, install_time); + histogram_tester_.ExpectBucketCount(kDayZeroOnInstallTime, 15, 2); + histogram_tester_.ExpectTotalCount(kDayZeroOffInstallTime, 0); +} +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) + } // namespace misc_metrics diff --git a/components/misc_metrics/pref_names.h b/components/misc_metrics/pref_names.h index 104d107551b..5a2200b1072 100644 --- a/components/misc_metrics/pref_names.h +++ b/components/misc_metrics/pref_names.h @@ -59,6 +59,9 @@ inline constexpr char kMiscMetricsNewTabLocationBarEntriesStorage[] = "brave.misc_metrics.new_tab_location_bar_entries_storage"; inline constexpr char kMiscMetricsTotalLocationBarEntriesStorage[] = "brave.misc_metrics.total_location_bar_entries_storage"; + +inline constexpr char kMiscMetricsDayZeroAtInstall[] = + "brave.misc_metrics.day_zero_at_install"; } // namespace misc_metrics #endif // BRAVE_COMPONENTS_MISC_METRICS_PREF_NAMES_H_ diff --git a/components/p3a/metric_names.h b/components/p3a/metric_names.h index 7d74ead7dd3..4335f85dbed 100644 --- a/components/p3a/metric_names.h +++ b/components/p3a/metric_names.h @@ -257,6 +257,8 @@ inline constexpr auto kCollectedExpressHistograms = base::MakeFixedFlatSet(base::sorted_unique,{ "Brave.AIChat.UsageDaily.2", "Brave.Core.UsageDaily", + "Brave.DayZero.Off.InstallTime", + "Brave.DayZero.On.InstallTime", "Brave.Rewards.EnabledInstallationTime", "Brave.Search.DefaultEngine.4", "Brave.Today.IsEnabled", @@ -284,6 +286,8 @@ inline constexpr auto kEphemeralHistograms = "Brave.AIChat.UsageMonthly", "Brave.AIChat.UsageWeekly", "Brave.Core.FailedHTTPSUpgrades", + "Brave.DayZero.Off.InstallTime", + "Brave.DayZero.On.InstallTime", "Brave.Playlist.FirstTimeOffset", "Brave.Playlist.UsageDaysInWeek", "Brave.PrivacyHub.Views",