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 support for BAP reporting endpoint #8054

Merged
merged 1 commit into from
Feb 25, 2021
Merged
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
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: {
zenparsing marked this conversation as resolved.
Show resolved Hide resolved
success = true;
break;
}
default: {
BLOG(0, "Unexpected reponse code " << response.status_code);
break;
}
}

callback(success);
}

} // namespace promotion
} // namespace ledger
Loading