Skip to content

Commit

Permalink
Add support for BAP reporting endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
zenparsing committed Feb 24, 2021
1 parent 5228a6c commit 5326c21
Show file tree
Hide file tree
Showing 18 changed files with 409 additions and 21 deletions.
1 change: 1 addition & 0 deletions components/brave_rewards/browser/rewards_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void RewardsService::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kParametersMonthlyTipChoices, "");
registry->RegisterBooleanPref(prefs::kFetchOldBalance, true);
registry->RegisterBooleanPref(prefs::kEmptyBalanceChecked, false);
registry->RegisterBooleanPref(prefs::kBAPReported, false);
registry->RegisterStringPref(prefs::kWalletBrave, "");
registry->RegisterStringPref(prefs::kWalletUphold, "");
}
Expand Down
3 changes: 3 additions & 0 deletions components/brave_rewards/browser/rewards_service_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,9 @@ bool RewardsServiceImpl::GetBooleanOption(const std::string& name) const {
return false;
}

if (name == ledger::option::kShouldReportBAPAmount)
return OnlyAnonWallet();

const auto it = kBoolOptions.find(name);
DCHECK(it != kBoolOptions.end());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ void RewardsBrowserTestResponse::Get(
return;
}

if (url.find("/v1/promotions/report-bap") != std::string::npos) {
*response = "";
*response_status_code = net::HTTP_OK;
return;
}

if (url.find("/v1/captchas") != std::string::npos) {
*response = captcha_;
}
Expand Down
33 changes: 33 additions & 0 deletions components/brave_rewards/browser/test/rewards_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#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 "brave/components/brave_rewards/common/pref_names.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
Expand Down Expand Up @@ -522,4 +523,36 @@ IN_PROC_BROWSER_TEST_F(RewardsBrowserTest, BAPPopup) {
EXPECT_TRUE(popup_shown);
}

IN_PROC_BROWSER_TEST_F(RewardsBrowserTest, BAPReporting) {
rewards_browsertest_util::StartProcess(rewards_service_);
rewards_browsertest_util::CreateWallet(rewards_service_);
rewards_service_->FetchPromotions();
promotion_->WaitForPromotionInitialization();
promotion_->ClaimPromotionViaCode();

rewards_browsertest_util::WaitForLedgerStop(rewards_service_);

rewards_browsertest_util::StartProcess(rewards_service_);
auto* prefs = browser()->profile()->GetPrefs();
rewards_browsertest_util::WaitForLedgerStop(rewards_service_);

EXPECT_FALSE(prefs->GetBoolean(brave_rewards::prefs::kBAPReported));

prefs->SetInteger(country_codes::kCountryIDAtInstall, 19024);

base::RunLoop run_loop;
PrefChangeRegistrar prefs_listener;
prefs_listener.Init(browser()->profile()->GetPrefs());
prefs_listener.Add(brave_rewards::prefs::kBAPReported,
base::BindLambdaForTesting(
[&run_loop](const std::string&) { run_loop.Quit(); }));

// Start the ledger process and wait for pref to be set, indicating that the
// reporting completed successfully.
rewards_browsertest_util::StartProcess(rewards_service_);
run_loop.Run();

EXPECT_TRUE(prefs->GetBoolean(brave_rewards::prefs::kBAPReported));
}

} // namespace rewards_browsertest
1 change: 1 addition & 0 deletions components/brave_rewards/common/pref_names.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const char kFetchOldBalance[] =
"brave.rewards.fetch_old_balance";
const char kEmptyBalanceChecked[] =
"brave.rewards.empty_balance_checked";
const char kBAPReported[] = "brave.rewards.bap_reported";
const char kWalletBrave[] =
"brave.rewards.wallets.brave";
const char kWalletUphold[] =
Expand Down
1 change: 1 addition & 0 deletions components/brave_rewards/common/pref_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ extern const char kParametersTipChoices[];
extern const char kParametersMonthlyTipChoices[];
extern const char kFetchOldBalance[];
extern const char kEmptyBalanceChecked[];
extern const char kBAPReported[];
extern const char kWalletBrave[];
extern const char kWalletUphold[];

Expand Down
4 changes: 4 additions & 0 deletions vendor/bat-native-ledger/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,10 @@ source_set("ledger") {
"src/bat/ledger/internal/logging/logging.h",
"src/bat/ledger/internal/logging/logging_util.cc",
"src/bat/ledger/internal/logging/logging_util.h",
"src/bat/ledger/internal/promotion/bap_reporter.cc",
"src/bat/ledger/internal/promotion/bap_reporter.h",
"src/bat/ledger/internal/promotion/bap_reporter_endpoint.cc",
"src/bat/ledger/internal/promotion/bap_reporter_endpoint.h",
"src/bat/ledger/internal/promotion/promotion.cc",
"src/bat/ledger/internal/promotion/promotion.h",
"src/bat/ledger/internal/promotion/promotion_transfer.cc",
Expand Down
7 changes: 4 additions & 3 deletions vendor/bat-native-ledger/include/bat/ledger/option_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* 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/. */

#ifndef BRAVELEDGER_OPTION_KEYS_H_
#define BRAVELEDGER_OPTION_KEYS_H_
#ifndef BRAVE_VENDOR_BAT_NATIVE_LEDGER_INCLUDE_BAT_LEDGER_OPTION_KEYS_H_
#define BRAVE_VENDOR_BAT_NATIVE_LEDGER_INCLUDE_BAT_LEDGER_OPTION_KEYS_H_

#include <string>

Expand All @@ -15,8 +15,9 @@ const char kPublisherListRefreshInterval[] = "publisher_list_refresh_interval";
const char kClaimUGP[] = "claim_ugp";
const char kContributionsDisabledForBAPMigration[] =
"contributions_disabled_for_bap_migration";
const char kShouldReportBAPAmount[] = "should_report_bap";

} // namespace option
} // namespace ledger

#endif // BRAVELEDGER_OPTION_KEYS_H_
#endif // BRAVE_VENDOR_BAT_NATIVE_LEDGER_INCLUDE_BAT_LEDGER_OPTION_KEYS_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* 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 "bat/ledger/internal/promotion/bap_reporter.h"

#include "base/time/time.h"
#include "bat/ledger/global_constants.h"
#include "bat/ledger/internal/common/time_util.h"
#include "bat/ledger/internal/ledger_impl.h"
#include "bat/ledger/option_keys.h"

using std::placeholders::_1;
using std::placeholders::_2;

namespace ledger {
namespace promotion {

namespace {

constexpr int64_t kRetryDelay = 24 * base::Time::kSecondsPerHour;
constexpr int64_t kRetryAfterFailureDelay = 10 * base::Time::kSecondsPerMinute;
constexpr int64_t kMaxRetryAfterFailureDelay = 4 * base::Time::kSecondsPerHour;

} // namespace

BAPReporter::BAPReporter(LedgerImpl* ledger)
: ledger_(ledger), endpoint_(ledger) {
DCHECK(ledger);
}

BAPReporter::~BAPReporter() = default;

void BAPReporter::ReportBAPAmount() {
if (running_)
return;

timer_.Stop();

bool should_report = ledger_->ledger_client()->GetBooleanOption(
option::kShouldReportBAPAmount);

// Only run this reporter if the user is in a BAP region and we haven't
// successfully reported yet.
if (!should_report || ledger_->state()->GetBAPReported())
return;

running_ = true;

// First, get the user's unspent BAP tokens.
ledger_->database()->GetSpendableUnblindedTokensByBatchTypes(
{type::CredsBatchType::PROMOTION},
std::bind(&BAPReporter::OnUnblindedTokens, this, _1));
}

void BAPReporter::OnUnblindedTokens(
std::vector<type::UnblindedTokenPtr> tokens) {
double amount = 0;
for (const auto& token : tokens)
amount += token->value;

// If the user has no BAP, then schedule a retry and exit.
if (amount <= 0) {
ScheduleRetryAfterZeroBalance();
return;
}

// Send the amount to the server.
endpoint_.Request(amount,
std::bind(&BAPReporter::OnEndpointResponse, this, _1));
}

void BAPReporter::OnEndpointResponse(bool success) {
// If the server reported an error, assume a temporary problem and try again
// later.
if (!success) {
ScheduleRetryAfterFailure();
return;
}

BLOG(1, "BAP successsfully reported");

// Set a flag to indicate that we don't need to report again.
ledger_->state()->SetBAPReported(true);
running_ = false;
retry_count_ = 0;
}

void BAPReporter::ScheduleRetryAfterZeroBalance() {
running_ = false;

base::TimeDelta delay = base::TimeDelta::FromSeconds(kRetryDelay);

BLOG(1, "User has zero balance - rescheduling BAP reporting in " << delay);
timer_.Start(
FROM_HERE, delay,
base::BindOnce(&BAPReporter::ReportBAPAmount, base::Unretained(this)));
}

void BAPReporter::ScheduleRetryAfterFailure() {
running_ = false;

base::TimeDelta delay = util::GetRandomizedDelayWithBackoff(
base::TimeDelta::FromSeconds(kRetryAfterFailureDelay),
base::TimeDelta::FromSeconds(kMaxRetryAfterFailureDelay), retry_count_++);

BLOG(1, "BAP reporting failed - rescheduling in " << delay);
timer_.Start(
FROM_HERE, delay,
base::BindOnce(&BAPReporter::ReportBAPAmount, base::Unretained(this)));
}

} // namespace promotion
} // namespace ledger
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* 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/. */

#ifndef BRAVE_VENDOR_BAT_NATIVE_LEDGER_SRC_BAT_LEDGER_INTERNAL_PROMOTION_BAP_REPORTER_H_
#define BRAVE_VENDOR_BAT_NATIVE_LEDGER_SRC_BAT_LEDGER_INTERNAL_PROMOTION_BAP_REPORTER_H_

#include <functional>
#include <vector>

#include "base/timer/timer.h"
#include "bat/ledger/internal/promotion/bap_reporter_endpoint.h"
#include "bat/ledger/ledger.h"

namespace ledger {

class LedgerImpl;

namespace promotion {

class BAPReporter {
public:
explicit BAPReporter(LedgerImpl* ledger);

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

~BAPReporter();

void ReportBAPAmount();

private:
void OnUnblindedTokens(std::vector<type::UnblindedTokenPtr> tokens);
void OnEndpointResponse(bool success);
void ScheduleRetryAfterZeroBalance();
void ScheduleRetryAfterFailure();

LedgerImpl* ledger_;
bool running_ = false;
int retry_count_ = 0;
base::OneShotTimer timer_;
BAPReporterEndpoint endpoint_;
};

} // namespace promotion
} // namespace ledger

#endif // BRAVE_VENDOR_BAT_NATIVE_LEDGER_SRC_BAT_LEDGER_INTERNAL_PROMOTION_BAP_REPORTER_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* 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 "bat/ledger/internal/promotion/bap_reporter_endpoint.h"

#include <string>
#include <utility>
#include <vector>

#include "base/json/json_writer.h"
#include "bat/ledger/internal/common/request_util.h"
#include "bat/ledger/internal/endpoint/promotion/promotions_util.h"
#include "bat/ledger/internal/ledger_impl.h"
#include "net/http/http_status_code.h"

using std::placeholders::_1;

namespace ledger {
namespace promotion {

namespace {

const char kEndpointPath[] = "/v1/promotions/report-bap";

} // namespace

BAPReporterEndpoint::BAPReporterEndpoint(LedgerImpl* ledger) : ledger_(ledger) {
DCHECK(ledger_);
}

BAPReporterEndpoint::~BAPReporterEndpoint() = default;

void BAPReporterEndpoint::Request(double amount, Callback callback) {
const auto wallet = ledger_->wallet()->GetWallet();
if (!wallet) {
BLOG(0, "Wallet is null");
callback(false);
return;
}

base::Value body(base::Value::Type::DICTIONARY);
body.SetDoubleKey("amount", amount);
std::string payload;
base::JSONWriter::Write(body, &payload);

const std::string sign_url = std::string("post ") + kEndpointPath;
auto headers = util::BuildSignHeaders(sign_url, payload, wallet->payment_id,
wallet->recovery_seed);

auto request = type::UrlRequest::New();
request->url = endpoint::promotion::GetServerUrl(kEndpointPath);
request->headers = std::move(headers);
request->content = std::move(payload);
request->content_type = "application/json; charset=utf-8";
request->method = type::UrlMethod::POST;
ledger_->LoadURL(
std::move(request),
std::bind(&BAPReporterEndpoint::OnFetchCompleted, this, callback, _1));
}

void BAPReporterEndpoint::OnFetchCompleted(Callback callback,
const type::UrlResponse& response) {
ledger::LogUrlResponse(__func__, response);

bool success = false;
switch (response.status_code) {
case net::HTTP_BAD_REQUEST: {
BLOG(0, "Invalid request");
break;
}
case net::HTTP_INTERNAL_SERVER_ERROR: {
BLOG(0, "Internal server error");
break;
}
case net::HTTP_OK:
case net::HTTP_CONFLICT: {
success = true;
break;
}
default: {
BLOG(0, "Unexpected reponse code " << response.status_code);
break;
}
}

callback(success);
}

} // namespace promotion
} // namespace ledger
Loading

0 comments on commit 5326c21

Please sign in to comment.