From 98c27ab3ef38896bd9a75b080186aceede343c29 Mon Sep 17 00:00:00 2001 From: Emerick Rogul Date: Mon, 26 Apr 2021 11:43:39 -0400 Subject: [PATCH 1/2] Add support for P3A wallet state (Q11) --- .../brave_ads/browser/ads_service_impl.cc | 3 +- .../brave_rewards/browser/rewards_p3a.cc | 97 ++++++++++++------- .../brave_rewards/browser/rewards_p3a.h | 38 +++++--- .../brave_rewards/browser/rewards_service.cc | 1 + .../browser/rewards_service_impl.cc | 69 ++++++++----- .../browser/rewards_service_impl.h | 2 + components/brave_rewards/common/pref_names.cc | 1 + components/brave_rewards/common/pref_names.h | 1 + components/p3a/brave_p3a_service.cc | 3 +- 9 files changed, 139 insertions(+), 76 deletions(-) diff --git a/components/brave_ads/browser/ads_service_impl.cc b/components/brave_ads/browser/ads_service_impl.cc index 84853aaeeef6..f564d532faf9 100644 --- a/components/brave_ads/browser/ads_service_impl.cc +++ b/components/brave_ads/browser/ads_service_impl.cc @@ -1708,7 +1708,8 @@ void AdsServiceImpl::OnPrefsChanged(const std::string& pref) { } // Record P3A. - brave_rewards::UpdateAdsP3AOnPreferenceChange(profile_->GetPrefs(), pref); + brave_rewards::p3a::UpdateAdsStateOnPreferenceChange(profile_->GetPrefs(), + pref); } else if (pref == ads::prefs::kIdleTimeThreshold) { StartCheckIdleStateTimer(); } else if (pref == brave_rewards::prefs::kWalletBrave) { diff --git a/components/brave_rewards/browser/rewards_p3a.cc b/components/brave_rewards/browser/rewards_p3a.cc index 4ce706c730c6..80b20bef02d0 100644 --- a/components/brave_rewards/browser/rewards_p3a.cc +++ b/components/brave_rewards/browser/rewards_p3a.cc @@ -14,10 +14,41 @@ #include "brave/components/brave_rewards/common/pref_names.h" #include "components/prefs/pref_service.h" +namespace { + +uint64_t RoundProbiToUint64(base::StringPiece probi) { + if (probi.size() < 18) + return 0; + uint64_t grant = 0; + base::StringToUint64(probi.substr(0, probi.size() - 18), &grant); + return grant; +} + +} // namespace + namespace brave_rewards { +namespace p3a { -void RecordWalletBalanceP3A(bool wallet_created, bool rewards_enabled, - size_t b) { +void RecordWalletState(const WalletState& state) { + int answer = 0; + if (state.wallet_created && !state.rewards_enabled) { + answer = 5; + } else if (state.rewards_enabled) { + DCHECK(state.wallet_created); + if (state.grants_claimed && state.funds_added) { + answer = 4; + } else if (state.funds_added) { + answer = 3; + } else if (state.grants_claimed) { + answer = 2; + } else { + answer = 1; + } + } + UMA_HISTOGRAM_EXACT_LINEAR("Brave.Rewards.WalletState", answer, 5); +} + +void RecordWalletBalance(bool wallet_created, bool rewards_enabled, size_t b) { int answer = 0; if (wallet_created && !rewards_enabled) { answer = 1; @@ -34,19 +65,19 @@ void RecordWalletBalanceP3A(bool wallet_created, bool rewards_enabled, UMA_HISTOGRAM_EXACT_LINEAR("Brave.Rewards.WalletBalance.2", answer, 4); } -void RecordAutoContributionsState(AutoContributionsP3AState state, int count) { +void RecordAutoContributionsState(AutoContributionsState state, int count) { DCHECK_GE(count, 0); int answer = 0; switch (state) { - case AutoContributionsP3AState::kNoWallet: + case AutoContributionsState::kNoWallet: break; - case AutoContributionsP3AState::kRewardsDisabled: + case AutoContributionsState::kRewardsDisabled: answer = 1; break; - case AutoContributionsP3AState::kWalletCreatedAutoContributeOff: + case AutoContributionsState::kWalletCreatedAutoContributeOff: answer = 2; break; - case AutoContributionsP3AState::kAutoContributeOn: + case AutoContributionsState::kAutoContributeOn: switch (count) { case 0: answer = 3; @@ -90,75 +121,66 @@ void RecordTipsState(bool wallet_created, UMA_HISTOGRAM_EXACT_LINEAR("Brave.Rewards.TipsState.2", answer, 5); } -void RecordAdsState(AdsP3AState state) { +void RecordAdsState(AdsState state) { UMA_HISTOGRAM_ENUMERATION("Brave.Rewards.AdsState.2", state); } -void UpdateAdsP3AOnPreferenceChange(PrefService *prefs, - const std::string& pref) { +void UpdateAdsStateOnPreferenceChange(PrefService* prefs, + const std::string& pref) { const bool ads_enabled = prefs->GetBoolean(ads::prefs::kEnabled); if (pref == ads::prefs::kEnabled) { if (ads_enabled) { - brave_rewards::RecordAdsState(AdsP3AState::kAdsEnabled); + RecordAdsState(AdsState::kAdsEnabled); prefs->SetBoolean(brave_ads::prefs::kAdsWereDisabled, false); } else { // Apparently, the pref was disabled. - brave_rewards::RecordAdsState( - AdsP3AState::kAdsEnabledThenDisabledRewardsOn); + RecordAdsState(AdsState::kAdsEnabledThenDisabledRewardsOn); prefs->SetBoolean(brave_ads::prefs::kAdsWereDisabled, true); } } } -void MaybeRecordInitialAdsP3AState(PrefService* prefs) { +void MaybeRecordInitialAdsState(PrefService* prefs) { if (!prefs->GetBoolean(brave_ads::prefs::kHasAdsP3AState)) { const bool ads_state = prefs->GetBoolean(ads::prefs::kEnabled); - RecordAdsState(ads_state ? AdsP3AState::kAdsEnabled - : AdsP3AState::kAdsDisabled); + RecordAdsState(ads_state ? AdsState::kAdsEnabled : AdsState::kAdsDisabled); prefs->SetBoolean(brave_ads::prefs::kHasAdsP3AState, true); } } void RecordNoWalletCreatedForAllMetrics() { - RecordWalletBalanceP3A(false, false, 0); - RecordAutoContributionsState(AutoContributionsP3AState::kNoWallet, 0); + RecordWalletState({}); + RecordWalletBalance(false, false, 0); + RecordAutoContributionsState(AutoContributionsState::kNoWallet, 0); RecordTipsState(false, false, 0, 0); - RecordAdsState(AdsP3AState::kNoWallet); + RecordAdsState(AdsState::kNoWallet); } void RecordRewardsDisabledForSomeMetrics() { - RecordWalletBalanceP3A(true, false, 1); - RecordAutoContributionsState(AutoContributionsP3AState::kRewardsDisabled, 0); + RecordWalletBalance(true, false, 1); + RecordAutoContributionsState(AutoContributionsState::kRewardsDisabled, 0); RecordTipsState(true, false, 0, 0); // Ads state is handled separately. } - -double CalcWalletBalanceForP3A(base::flat_map wallets, - double user_funds) { +double CalcWalletBalance(base::flat_map wallets, + double user_funds) { double balance_minus_grant = 0.0; for (const auto& wallet : wallets) { - // Skip anonymous wallet, since it can contain grants. - if (wallet.first == "anonymous") { + // Skip anonymous and unblinded wallets, since they can contain grants. + if (wallet.first == "anonymous" || wallet.first == "blinded") { continue; } balance_minus_grant += static_cast(wallet.second); } - // `user_funds` is the amount of user-funded BAT - // in the anonymous wallet (ex: not grants). + // |user_funds| is the amount of user-funded BAT in the anonymous + // wallet (ex: not grants). balance_minus_grant += user_funds; return balance_minus_grant; } -uint64_t RoundProbiToUint64(base::StringPiece probi) { - if (probi.size() < 18) return 0; - uint64_t grant = 0; - base::StringToUint64(probi.substr(0, probi.size() - 18), &grant); - return grant; -} - -void ExtractAndLogP3AStats(const base::DictionaryValue& dict) { +void ExtractAndLogStats(const base::DictionaryValue& dict) { const base::Value* probi_value = dict.FindPath({"walletProperties", "probi_"}); if (!probi_value || !probi_value->is_string()) { @@ -195,7 +217,8 @@ void ExtractAndLogP3AStats(const base::DictionaryValue& dict) { } const uint64_t total = RoundProbiToUint64(probi_value->GetString()) - total_grants; - RecordWalletBalanceP3A(true, true, total); + RecordWalletBalance(true, true, total); } +} // namespace p3a } // namespace brave_rewards diff --git a/components/brave_rewards/browser/rewards_p3a.h b/components/brave_rewards/browser/rewards_p3a.h index f726404addf9..ee1ed36b769f 100644 --- a/components/brave_rewards/browser/rewards_p3a.h +++ b/components/brave_rewards/browser/rewards_p3a.h @@ -21,25 +21,36 @@ class DictionaryValue; } namespace brave_rewards { +namespace p3a { -void RecordWalletBalanceP3A(bool wallet_created, bool rewards_enabled, - size_t balance); +struct WalletState { + bool wallet_created = false; + bool rewards_enabled = false; + bool grants_claimed = false; + bool funds_added = false; +}; + +void RecordWalletState(const WalletState& state); -enum class AutoContributionsP3AState { +void RecordWalletBalance(bool wallet_created, + bool rewards_enabled, + size_t balance); + +enum class AutoContributionsState { kNoWallet, kRewardsDisabled, kWalletCreatedAutoContributeOff, kAutoContributeOn, }; -void RecordAutoContributionsState(AutoContributionsP3AState state, int count); +void RecordAutoContributionsState(AutoContributionsState state, int count); void RecordTipsState(bool wallet_created, bool rewards_enabled, int one_time_count, int recurring_count); -enum class AdsP3AState { +enum class AdsState { kNoWallet, kRewardsDisabled, kAdsDisabled, @@ -49,26 +60,25 @@ enum class AdsP3AState { kMaxValue = kAdsEnabledThenDisabledRewardsOff, }; -void RecordAdsState(AdsP3AState state); +void RecordAdsState(AdsState state); -void UpdateAdsP3AOnPreferenceChange(PrefService* prefs, - const std::string& pref); +void UpdateAdsStateOnPreferenceChange(PrefService* prefs, + const std::string& pref); // Records an initial metric state ("disabled" or "enabled") if it was not done // before. Intended to be called if the user has already created a wallet. -void MaybeRecordInitialAdsP3AState(PrefService* local_state); +void MaybeRecordInitialAdsState(PrefService* local_state); void RecordNoWalletCreatedForAllMetrics(); void RecordRewardsDisabledForSomeMetrics(); -double CalcWalletBalanceForP3A(base::flat_map wallets, - double user_funds); - -uint64_t RoundProbiToUint64(base::StringPiece probi); +double CalcWalletBalance(base::flat_map wallets, + double user_funds); -void ExtractAndLogP3AStats(const base::DictionaryValue& dict); +void ExtractAndLogStats(const base::DictionaryValue& dict); +} // namespace p3a } // namespace brave_rewards #endif // BRAVE_COMPONENTS_BRAVE_REWARDS_BROWSER_REWARDS_P3A_H_ diff --git a/components/brave_rewards/browser/rewards_service.cc b/components/brave_rewards/browser/rewards_service.cc index fca3766f96ec..4ec3c33ee5f5 100644 --- a/components/brave_rewards/browser/rewards_service.cc +++ b/components/brave_rewards/browser/rewards_service.cc @@ -52,6 +52,7 @@ void RewardsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { base::TimeDelta::FromSeconds(30)); registry->RegisterBooleanPref(prefs::kBackupSucceeded, false); registry->RegisterBooleanPref(prefs::kUserHasFunded, false); + registry->RegisterBooleanPref(prefs::kUserHasClaimedGrant, false); registry->RegisterTimePref(prefs::kAddFundsNotification, base::Time()); registry->RegisterBooleanPref(prefs::kEnabled, false); registry->RegisterDictionaryPref(prefs::kExternalWallets); diff --git a/components/brave_rewards/browser/rewards_service_impl.cc b/components/brave_rewards/browser/rewards_service_impl.cc index 71e4efa45151..8c036b9c26ae 100644 --- a/components/brave_rewards/browser/rewards_service_impl.cc +++ b/components/brave_rewards/browser/rewards_service_impl.cc @@ -91,8 +91,6 @@ #include "brave/components/ipfs/ipfs_utils.h" #endif using net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES; -using std::placeholders::_1; -using std::placeholders::_2; namespace brave_rewards { @@ -166,7 +164,7 @@ std::pair LoadStateOnFileTaskRunner( return result; } - ExtractAndLogP3AStats(*dict); + p3a::ExtractAndLogStats(*dict); result.second = std::move(*dict); return result; @@ -418,8 +416,8 @@ void RewardsServiceImpl::OnPreferenceChanged(const std::string& key) { StartLedgerProcessIfNecessary(); } else { // Just record the disabled state. - RecordAutoContributionsState( - AutoContributionsP3AState::kWalletCreatedAutoContributeOff, 0); + p3a::RecordAutoContributionsState( + p3a::AutoContributionsState::kWalletCreatedAutoContributeOff, 0); } } @@ -427,7 +425,8 @@ void RewardsServiceImpl::OnPreferenceChanged(const std::string& key) { if (IsRewardsEnabled()) { RecordBackendP3AStats(); } else { - RecordRewardsDisabledForSomeMetrics(); + p3a::RecordRewardsDisabledForSomeMetrics(); + p3a::RecordWalletState({.wallet_created = true}); } } } @@ -842,14 +841,24 @@ void RewardsServiceImpl::OnLedgerInitialized(ledger::type::Result result) { if (IsRewardsEnabled()) { RecordBackendP3AStats(); } else { - RecordRewardsDisabledForSomeMetrics(); + p3a::RecordRewardsDisabledForSomeMetrics(); } + GetBraveWallet( + base::BindOnce(&RewardsServiceImpl::OnGetBraveWalletForP3A, AsWeakPtr())); + for (auto& observer : observers_) { observer.OnRewardsInitialized(this); } } +void RewardsServiceImpl::OnGetBraveWalletForP3A( + ledger::type::BraveWalletPtr wallet) { + if (!wallet) { + p3a::RecordNoWalletCreatedForAllMetrics(); + } +} + void RewardsServiceImpl::OnGetAutoContributeProperties( const GetAutoContributePropertiesCallback& callback, ledger::type::AutoContributePropertiesPtr properties) { @@ -921,10 +930,10 @@ void RewardsServiceImpl::OnLedgerStateLoaded( if (state.second.is_dict()) { // Record stats. RecordBackendP3AStats(); - MaybeRecordInitialAdsP3AState(profile_->GetPrefs()); + p3a::MaybeRecordInitialAdsState(profile_->GetPrefs()); } if (state.first.empty()) { - RecordNoWalletCreatedForAllMetrics(); + p3a::RecordNoWalletCreatedForAllMetrics(); } // Run callbacks. @@ -1312,6 +1321,9 @@ void RewardsServiceImpl::OnAttestPromotion( return; } + PrefService* pref_service = profile_->GetPrefs(); + pref_service->SetBoolean(prefs::kUserHasClaimedGrant, true); + for (auto& observer : observers_) { observer.OnPromotionFinished(this, result, promotion->Clone()); } @@ -2767,19 +2779,29 @@ void RewardsServiceImpl::OnFetchBalance( FetchBalanceCallback callback, const ledger::type::Result result, ledger::type::BalancePtr balance) { + PrefService* pref_service = profile_->GetPrefs(); + + // Record wallet state stats + if (IsRewardsEnabled()) { + const bool grants_claimed = + pref_service->GetBoolean(prefs::kUserHasClaimedGrant); + p3a::RecordWalletState( + {.wallet_created = true, + .rewards_enabled = true, + .grants_claimed = grants_claimed, + .funds_added = balance && balance->user_funds > 0}); + } + if (balance) { if (balance->total > 0) { - profile_->GetPrefs()->SetBoolean(prefs::kUserHasFunded, true); + pref_service->SetBoolean(prefs::kUserHasFunded, true); } - // Record stats. - double balance_minus_grant = CalcWalletBalanceForP3A( - balance->wallets, - balance->user_funds); - RecordWalletBalanceP3A( - true, - true, - static_cast(balance_minus_grant)); + // Record wallet balance stats + double balance_minus_grant = + p3a::CalcWalletBalance(balance->wallets, balance->user_funds); + p3a::RecordWalletBalance(true, true, + static_cast(balance_minus_grant)); } std::move(callback).Run(result, std::move(balance)); @@ -3012,7 +3034,7 @@ void RewardsServiceImpl::OnRecordBackendP3AStatsContributions( queued_recurring = recurring_donation_size; } - RecordTipsState(true, true, tips, queued_recurring); + p3a::RecordTipsState(true, true, tips, queued_recurring); GetAutoContributeEnabled(base::BindOnce( &RewardsServiceImpl::OnRecordBackendP3AStatsAC, @@ -3023,10 +3045,11 @@ void RewardsServiceImpl::OnRecordBackendP3AStatsContributions( void RewardsServiceImpl::OnRecordBackendP3AStatsAC( const int auto_contributions, bool ac_enabled) { - const auto auto_contributions_state = ac_enabled ? - AutoContributionsP3AState::kAutoContributeOn : - AutoContributionsP3AState::kWalletCreatedAutoContributeOff; - RecordAutoContributionsState(auto_contributions_state, auto_contributions); + const auto auto_contributions_state = + ac_enabled ? p3a::AutoContributionsState::kAutoContributeOn + : p3a::AutoContributionsState::kWalletCreatedAutoContributeOff; + p3a::RecordAutoContributionsState(auto_contributions_state, + auto_contributions); } #if defined(OS_ANDROID) diff --git a/components/brave_rewards/browser/rewards_service_impl.h b/components/brave_rewards/browser/rewards_service_impl.h index 871d6823c3d6..67351041c388 100644 --- a/components/brave_rewards/browser/rewards_service_impl.h +++ b/components/brave_rewards/browser/rewards_service_impl.h @@ -688,6 +688,8 @@ class RewardsServiceImpl : public RewardsService, const std::string& publisher_key, const std::string& publisher_name) override; + void OnGetBraveWalletForP3A(ledger::type::BraveWalletPtr wallet); + bool Connected() const; void ConnectionClosed(); void AddPrivateObserver(RewardsServicePrivateObserver* observer) override; diff --git a/components/brave_rewards/common/pref_names.cc b/components/brave_rewards/common/pref_names.cc index 42e0efc3fa98..da6c30300f9c 100644 --- a/components/brave_rewards/common/pref_names.cc +++ b/components/brave_rewards/common/pref_names.cc @@ -17,6 +17,7 @@ const char kBackupNotificationInterval[] = "brave.rewards.backup_notification_interval"; const char kBackupSucceeded[] = "brave.rewards.backup_succeeded"; const char kUserHasFunded[] = "brave.rewards.user_has_funded"; +const char kUserHasClaimedGrant[] = "brave.rewards.user_has_claimed_grant"; const char kAddFundsNotification[] = "brave.rewards.add_funds_notification"; const char kNotificationStartupDelay[] = diff --git a/components/brave_rewards/common/pref_names.h b/components/brave_rewards/common/pref_names.h index cbc10fb755a3..30e1511ac891 100644 --- a/components/brave_rewards/common/pref_names.h +++ b/components/brave_rewards/common/pref_names.h @@ -16,6 +16,7 @@ extern const char kNotificationTimerInterval[]; extern const char kBackupNotificationInterval[]; extern const char kBackupSucceeded[]; extern const char kUserHasFunded[]; +extern const char kUserHasClaimedGrant[]; extern const char kAddFundsNotification[]; extern const char kNotificationStartupDelay[]; extern const char kExternalWallets[]; // DEPRECATED diff --git a/components/p3a/brave_p3a_service.cc b/components/p3a/brave_p3a_service.cc index a84b6498494c..9e7444a777e6 100644 --- a/components/p3a/brave_p3a_service.cc +++ b/components/p3a/brave_p3a_service.cc @@ -20,12 +20,12 @@ #include "base/strings/string_number_conversions.h" #include "base/task/post_task.h" #include "base/trace_event/trace_event.h" -#include "brave/components/brave_stats/browser/brave_stats_updater_util.h" #include "brave/browser/version_info.h" #include "brave/common/brave_channel_info.h" #include "brave/common/pref_names.h" #include "brave/components/brave_prochlo/prochlo_message.pb.h" #include "brave/components/brave_referrals/common/pref_names.h" +#include "brave/components/brave_stats/browser/brave_stats_updater_util.h" #include "brave/components/p3a/brave_p2a_protocols.h" #include "brave/components/p3a/brave_p3a_log_store.h" #include "brave/components/p3a/brave_p3a_scheduler.h" @@ -80,6 +80,7 @@ constexpr const char* kCollectedHistograms[] = { "Brave.Rewards.AutoContributionsState.2", "Brave.Rewards.TipsState.2", "Brave.Rewards.WalletBalance.2", + "Brave.Rewards.WalletState", "Brave.Savings.BandwidthSavingsMB", "Brave.Search.DefaultEngine.4", "Brave.Shields.UsageStatus", From 2d95b4d8fe3f69210f65a6a598197fdd32148fe4 Mon Sep 17 00:00:00 2001 From: Emerick Rogul Date: Tue, 27 Apr 2021 17:54:12 -0400 Subject: [PATCH 2/2] Add tests for WalletState --- .../browser/rewards_service_impl.cc | 9 +- .../common/rewards_browsertest_contribution.h | 1 + .../browser/test/rewards_p3a_browsertest.cc | 222 ++++++++++++++++++ test/BUILD.gn | 1 + 4 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 components/brave_rewards/browser/test/rewards_p3a_browsertest.cc diff --git a/components/brave_rewards/browser/rewards_service_impl.cc b/components/brave_rewards/browser/rewards_service_impl.cc index 8c036b9c26ae..5c366d5d04c9 100644 --- a/components/brave_rewards/browser/rewards_service_impl.cc +++ b/components/brave_rewards/browser/rewards_service_impl.cc @@ -2785,11 +2785,10 @@ void RewardsServiceImpl::OnFetchBalance( if (IsRewardsEnabled()) { const bool grants_claimed = pref_service->GetBoolean(prefs::kUserHasClaimedGrant); - p3a::RecordWalletState( - {.wallet_created = true, - .rewards_enabled = true, - .grants_claimed = grants_claimed, - .funds_added = balance && balance->user_funds > 0}); + p3a::RecordWalletState({.wallet_created = true, + .rewards_enabled = true, + .grants_claimed = grants_claimed, + .funds_added = balance && balance->user_funds > 0}); } if (balance) { diff --git a/components/brave_rewards/browser/test/common/rewards_browsertest_contribution.h b/components/brave_rewards/browser/test/common/rewards_browsertest_contribution.h index cade306b21e3..72bb5e20b2ca 100644 --- a/components/brave_rewards/browser/test/common/rewards_browsertest_contribution.h +++ b/components/brave_rewards/browser/test/common/rewards_browsertest_contribution.h @@ -14,6 +14,7 @@ #include "bat/ledger/mojom_structs.h" #include "brave/components/brave_rewards/browser/rewards_service_impl.h" #include "brave/components/brave_rewards/browser/rewards_service_observer.h" +#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_context_helper.h" #include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_util.h" #include "chrome/browser/ui/browser.h" diff --git a/components/brave_rewards/browser/test/rewards_p3a_browsertest.cc b/components/brave_rewards/browser/test/rewards_p3a_browsertest.cc new file mode 100644 index 000000000000..e2467dfed7c1 --- /dev/null +++ b/components/brave_rewards/browser/test/rewards_p3a_browsertest.cc @@ -0,0 +1,222 @@ +/* Copyright (c) 2021 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 http://mozilla.org/MPL/2.0/. */ + +#include +#include + +#include "base/containers/flat_map.h" +#include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" +#include "brave/browser/brave_rewards/rewards_service_factory.h" +#include "brave/common/brave_paths.h" +#include "brave/components/brave_rewards/browser/rewards_service_impl.h" +#include "brave/components/brave_rewards/browser/rewards_service_observer.h" +#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_context_util.h" +#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_contribution.h" +#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_network_util.h" +#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_promotion.h" +#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_response.h" +#include "brave/components/brave_rewards/browser/test/common/rewards_browsertest_util.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "net/dns/mock_host_resolver.h" + +// npm run test -- brave_browser_tests --filter=RewardsP3ABrowserTest.* + +namespace rewards_browsertest { + +class RewardsP3ABrowserTest : public InProcessBrowserTest, + public brave_rewards::RewardsServiceObserver { + public: + RewardsP3ABrowserTest() { + contribution_ = std::make_unique(); + promotion_ = std::make_unique(); + response_ = std::make_unique(); + histogram_tester_.reset(new base::HistogramTester); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + + context_helper_ = + std::make_unique(browser()); + + // HTTP resolver + host_resolver()->AddRule("*", "127.0.0.1"); + https_server_.reset(new net::EmbeddedTestServer( + net::test_server::EmbeddedTestServer::TYPE_HTTPS)); + https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK); + https_server_->RegisterRequestHandler( + base::BindRepeating(&rewards_browsertest_util::HandleRequest)); + ASSERT_TRUE(https_server_->Start()); + + // Rewards service + brave::RegisterPathProvider(); + auto* profile = browser()->profile(); + rewards_service_ = static_cast( + brave_rewards::RewardsServiceFactory::GetForProfile(profile)); + rewards_service_->AddObserver(this); + + // Response mock + base::ScopedAllowBlockingForTesting allow_blocking; + response_->LoadMocks(); + rewards_service_->ForTestingSetTestResponseCallback(base::BindRepeating( + &RewardsP3ABrowserTest::GetTestResponse, base::Unretained(this))); + rewards_service_->SetLedgerEnvForTesting(); + + // Other + promotion_->Initialize(browser(), rewards_service_); + contribution_->Initialize(browser(), rewards_service_); + + rewards_browsertest_util::SetOnboardingBypassed(browser()); + } + + void TearDown() override { InProcessBrowserTest::TearDown(); } + + void SetUpCommandLine(base::CommandLine* command_line) override { + // HTTPS server only serves a valid cert for localhost, so this is needed + // to load pages from other hosts without an error + command_line->AppendSwitch(switches::kIgnoreCertificateErrors); + } + + void GetTestResponse(const std::string& url, + int32_t method, + int* response_status_code, + std::string* response, + base::flat_map* headers) { + response_->SetExternalBalance(contribution_->GetExternalBalance()); + response_->Get(url, method, response_status_code, response); + } + + void FetchBalance() { + base::RunLoop run_loop; + rewards_service_->FetchBalance(base::BindLambdaForTesting( + [&](ledger::type::Result result, ledger::type::BalancePtr balance) { + run_loop.Quit(); + })); + run_loop.Run(); + } + + void WaitForRewardsInitialization() { + if (rewards_initialized_) { + return; + } + + wait_for_rewards_initialization_loop_.reset(new base::RunLoop); + wait_for_rewards_initialization_loop_->Run(); + } + + content::WebContents* contents() { + return browser()->tab_strip_model()->GetActiveWebContents(); + } + + void OnRewardsInitialized( + brave_rewards::RewardsService* rewards_service) override { + rewards_initialized_ = true; + } + + brave_rewards::RewardsServiceImpl* rewards_service_; + std::unique_ptr https_server_; + std::unique_ptr contribution_; + std::unique_ptr promotion_; + std::unique_ptr response_; + std::unique_ptr context_helper_; + std::unique_ptr histogram_tester_; + + bool rewards_initialized_ = false; + std::unique_ptr wait_for_rewards_initialization_loop_; +}; + +IN_PROC_BROWSER_TEST_F(RewardsP3ABrowserTest, RewardsDisabled) { + rewards_browsertest_util::StartProcess(rewards_service_); + + WaitForRewardsInitialization(); + + histogram_tester_->ExpectBucketCount("Brave.Rewards.WalletBalance.2", 1, 1); + histogram_tester_->ExpectBucketCount("Brave.Rewards.AutoContributionsState.2", + 1, 1); + histogram_tester_->ExpectBucketCount("Brave.Rewards.TipsState.2", 1, 1); +} + +IN_PROC_BROWSER_TEST_F(RewardsP3ABrowserTest, + WalletStateWalletCreatedNoGrantsClaimedNoFundsAdded) { + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + + rewards_service_->SetAutoContributeEnabled(true); + rewards_service_->SetAdsEnabled(true); + + FetchBalance(); + + histogram_tester_->ExpectBucketCount("Brave.Rewards.WalletState", 1, 1); +} + +IN_PROC_BROWSER_TEST_F(RewardsP3ABrowserTest, + WalletStateWalletCreatedGrantsClaimedNoFundsAdded) { + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + + context_helper_->LoadURL(rewards_browsertest_util::GetRewardsUrl()); + + rewards_service_->SetAutoContributeEnabled(true); + rewards_service_->SetAdsEnabled(true); + + contribution_->AddBalance(promotion_->ClaimPromotionViaCode()); + + FetchBalance(); + + histogram_tester_->ExpectBucketCount("Brave.Rewards.WalletState", 2, 1); +} + +IN_PROC_BROWSER_TEST_F(RewardsP3ABrowserTest, + WalletStateWalletCreatedNoGrantsClaimedFundsAdded) { + response_->SetUserFundsBalance(true); + + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + + context_helper_->LoadURL(rewards_browsertest_util::GetRewardsUrl()); + + rewards_service_->SetAutoContributeEnabled(true); + rewards_service_->SetAdsEnabled(true); + + FetchBalance(); + + histogram_tester_->ExpectBucketCount("Brave.Rewards.WalletState", 3, 1); +} + +IN_PROC_BROWSER_TEST_F(RewardsP3ABrowserTest, + WalletStateWalletCreatedGrantsClaimedFundsAdded) { + response_->SetUserFundsBalance(true); + + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + + context_helper_->LoadURL(rewards_browsertest_util::GetRewardsUrl()); + + rewards_service_->SetAutoContributeEnabled(true); + rewards_service_->SetAdsEnabled(true); + + contribution_->AddBalance(promotion_->ClaimPromotionViaCode()); + + FetchBalance(); + + histogram_tester_->ExpectBucketCount("Brave.Rewards.WalletState", 4, 1); +} + +IN_PROC_BROWSER_TEST_F(RewardsP3ABrowserTest, + WalletStateWalletDisabledAfterCreation) { + rewards_browsertest_util::StartProcess(rewards_service_); + rewards_browsertest_util::CreateWallet(rewards_service_); + + rewards_service_->SetAdsEnabled(false); + rewards_service_->SetAutoContributeEnabled(false); + + histogram_tester_->ExpectBucketCount("Brave.Rewards.WalletState", 5, 1); +} + +} // namespace rewards_browsertest diff --git a/test/BUILD.gn b/test/BUILD.gn index ec72d003f093..df10e5262f61 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -726,6 +726,7 @@ if (!is_android) { "//brave/components/brave_rewards/browser/test/rewards_contribution_browsertest.cc", "//brave/components/brave_rewards/browser/test/rewards_flag_browsertest.cc", "//brave/components/brave_rewards/browser/test/rewards_notification_browsertest.cc", + "//brave/components/brave_rewards/browser/test/rewards_p3a_browsertest.cc", "//brave/components/brave_rewards/browser/test/rewards_promotion_browsertest.cc", "//brave/components/brave_rewards/browser/test/rewards_publisher_browsertest.cc", "//brave/components/brave_rewards/browser/test/rewards_state_browsertest.cc",