diff --git a/components/brave_rewards/content/rewards_service_impl.cc b/components/brave_rewards/content/rewards_service_impl.cc index 8a353b3d1774..13dfd66da1af 100644 --- a/components/brave_rewards/content/rewards_service_impl.cc +++ b/components/brave_rewards/content/rewards_service_impl.cc @@ -42,6 +42,7 @@ #include "brave/components/brave_rewards/content/service_sandbox_type.h" #include "brave/components/brave_rewards/core/buildflags/buildflags.h" #include "brave/components/brave_rewards/core/engine/global_constants.h" +#include "brave/components/brave_rewards/core/engine/hash_prefix_store.h" #include "brave/components/brave_rewards/core/engine/parameters/rewards_parameters_provider.h" #include "brave/components/brave_rewards/core/engine/rewards_database.h" #include "brave/components/brave_rewards/core/features.h" @@ -236,12 +237,14 @@ void DeferCallback(base::Location location, Callback callback, Args&&... args) { // read comment about file pathes at src\base\files\file_path.h #if BUILDFLAG(IS_WIN) const base::FilePath::StringType kDiagnosticLogPath(L"Rewards.log"); +const base::FilePath::StringType kCreatorPrefixStore(L"RewardsCreators.db"); const base::FilePath::StringType kLegacy_state(L"ledger_state"); const base::FilePath::StringType kPublisher_state(L"publisher_state"); const base::FilePath::StringType kPublisher_info_db(L"publisher_info_db"); const base::FilePath::StringType kPublishers_list(L"publishers_list"); #else const base::FilePath::StringType kDiagnosticLogPath("Rewards.log"); +const base::FilePath::StringType kCreatorPrefixStore("RewardsCreators.db"); const base::FilePath::StringType kLegacy_state("ledger_state"); const base::FilePath::StringType kPublisher_state("publisher_state"); const base::FilePath::StringType kPublisher_info_db("publisher_info_db"); @@ -272,9 +275,11 @@ RewardsServiceImpl::RewardsServiceImpl( publisher_state_path_(profile_path.Append(kPublisher_state)), publisher_info_db_path_(profile_path.Append(kPublisher_info_db)), publisher_list_path_(profile_path.Append(kPublishers_list)), + creator_prefix_store_path_(profile_path.Append(kCreatorPrefixStore)), diagnostic_log_(new DiagnosticLog(profile_path.Append(kDiagnosticLogPath), kDiagnosticLogMaxFileSize, kDiagnosticLogKeepNumLines)), + creator_prefix_store_(file_task_runner_), notification_service_(new RewardsNotificationServiceImpl(prefs)), conversion_monitor_(prefs) { ready_ = std::make_unique(); @@ -386,6 +391,8 @@ void RewardsServiceImpl::StartEngineProcessIfNecessary() { rewards_database_ = base::SequenceBound( file_task_runner_, publisher_info_db_path_); + creator_prefix_store_.BindRemote(creator_prefix_store_path_); + BLOG(1, "Starting engine process"); if (!engine_factory_.is_bound()) { @@ -1066,10 +1073,8 @@ void RewardsServiceImpl::OnDiagnosticLogDeletedForCompleteReset( bool success) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const std::vector paths = { - legacy_state_path_, - publisher_state_path_, - publisher_info_db_path_, - publisher_list_path_, + legacy_state_path_, publisher_state_path_, publisher_info_db_path_, + publisher_list_path_, creator_prefix_store_path_, }; file_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&DeleteFilesOnFileTaskRunner, paths), @@ -1092,6 +1097,7 @@ void RewardsServiceImpl::Reset() { engine_factory_.reset(); ready_ = std::make_unique(); rewards_database_.Reset(); + creator_prefix_store_.reset(); BLOG(1, "Successfully reset rewards service"); } @@ -2103,6 +2109,19 @@ void RewardsServiceImpl::OnRunDBTransaction( std::move(callback).Run(std::move(response)); } +void RewardsServiceImpl::UpdateCreatorPrefixStore( + mojom::HashPrefixDataPtr prefix_data, + UpdateCreatorPrefixStoreCallback callback) { + creator_prefix_store_->UpdatePrefixes(std::move(prefix_data), + std::move(callback)); +} + +void RewardsServiceImpl::CreatorPrefixStoreContains( + const std::string& value, + CreatorPrefixStoreContainsCallback callback) { + creator_prefix_store_->ContainsPrefix(value, std::move(callback)); +} + void RewardsServiceImpl::ForTestingSetTestResponseCallback( const GetTestResponseCallback& callback) { test_response_callback_ = callback; diff --git a/components/brave_rewards/content/rewards_service_impl.h b/components/brave_rewards/content/rewards_service_impl.h index 4a23a5d06392..fcb94027e875 100644 --- a/components/brave_rewards/content/rewards_service_impl.h +++ b/components/brave_rewards/content/rewards_service_impl.h @@ -26,7 +26,9 @@ #include "brave/components/brave_rewards/content/diagnostic_log.h" #include "brave/components/brave_rewards/content/rewards_p3a.h" #include "brave/components/brave_rewards/content/rewards_service.h" +#include "brave/components/brave_rewards/core/mojom/rewards_database.mojom.h" #include "brave/components/brave_rewards/core/mojom/rewards_engine.mojom.h" +#include "brave/components/brave_rewards/core/remote_worker.h" #include "brave/components/brave_rewards/core/rewards_flags.h" #include "brave/components/brave_wallet/browser/brave_wallet_service.h" #include "brave/components/brave_wallet/common/brave_wallet.mojom.h" @@ -429,6 +431,14 @@ class RewardsServiceImpl final : public RewardsService, void RunDBTransaction(mojom::DBTransactionPtr transaction, RunDBTransactionCallback callback) override; + void UpdateCreatorPrefixStore( + mojom::HashPrefixDataPtr prefix_data, + UpdateCreatorPrefixStoreCallback callback) override; + + void CreatorPrefixStoreContains( + const std::string& value, + CreatorPrefixStoreContainsCallback callback) override; + void ClearAllNotifications() override; void ExternalWalletConnected() override; @@ -502,9 +512,11 @@ class RewardsServiceImpl final : public RewardsService, const base::FilePath publisher_state_path_; const base::FilePath publisher_info_db_path_; const base::FilePath publisher_list_path_; + const base::FilePath creator_prefix_store_path_; std::unique_ptr diagnostic_log_; base::SequenceBound rewards_database_; + RemoteWorker creator_prefix_store_; std::unique_ptr notification_service_; std::unique_ptr extension_observer_; diff --git a/components/brave_rewards/core/BUILD.gn b/components/brave_rewards/core/BUILD.gn index 4279a5e55176..66b622e47626 100644 --- a/components/brave_rewards/core/BUILD.gn +++ b/components/brave_rewards/core/BUILD.gn @@ -22,6 +22,7 @@ static_library("core") { "pref_registry.h", "publisher_utils.cc", "publisher_utils.h", + "remote_worker.h", "rewards_flags.cc", "rewards_flags.h", "rewards_util.cc", @@ -33,6 +34,7 @@ static_library("core") { "//base", "//brave/components/l10n/common", "//components/prefs", + "//mojo/public/mojom/base", "//net", "//url", ] diff --git a/components/brave_rewards/core/engine/BUILD.gn b/components/brave_rewards/core/engine/BUILD.gn index 8c9bcdb3b636..e48541e43bab 100644 --- a/components/brave_rewards/core/engine/BUILD.gn +++ b/components/brave_rewards/core/engine/BUILD.gn @@ -146,8 +146,6 @@ static_library("engine") { "database/database_migration.h", "database/database_publisher_info.cc", "database/database_publisher_info.h", - "database/database_publisher_prefix_list.cc", - "database/database_publisher_prefix_list.h", "database/database_recurring_tip.cc", "database/database_recurring_tip.h", "database/database_server_publisher_banner.cc", @@ -203,6 +201,7 @@ static_library("engine") { "database/migration/migration_v39.h", "database/migration/migration_v4.h", "database/migration/migration_v40.h", + "database/migration/migration_v41.h", "database/migration/migration_v5.h", "database/migration/migration_v6.h", "database/migration/migration_v7.h", @@ -313,6 +312,9 @@ static_library("engine") { "endpoints/zebpay/post_oauth_zebpay.h", "gemini/gemini.cc", "gemini/gemini.h", + "hash_prefix_iterator.h", + "hash_prefix_store.cc", + "hash_prefix_store.h", "initialization_manager.cc", "initialization_manager.h", "legacy/bat_state.cc", @@ -343,7 +345,6 @@ static_library("engine") { "publisher/media/media.h", "publisher/media/youtube.cc", "publisher/media/youtube.h", - "publisher/prefix_iterator.h", "publisher/prefix_list_reader.cc", "publisher/prefix_list_reader.h", "publisher/prefix_util.cc", @@ -379,6 +380,8 @@ static_library("engine") { "state/state_migration_v13.h", "state/state_migration_v14.cc", "state/state_migration_v14.h", + "state/state_migration_v15.cc", + "state/state_migration_v15.h", "state/state_migration_v2.cc", "state/state_migration_v2.h", "state/state_migration_v3.cc", diff --git a/components/brave_rewards/core/engine/database/database.cc b/components/brave_rewards/core/engine/database/database.cc index 5d99aebdb714..ae2e8729f49e 100644 --- a/components/brave_rewards/core/engine/database/database.cc +++ b/components/brave_rewards/core/engine/database/database.cc @@ -26,7 +26,6 @@ Database::Database(RewardsEngine& engine) external_transactions_(engine), media_publisher_info_(engine), publisher_info_(engine), - publisher_prefix_list_(engine), recurring_tip_(engine), server_publisher_info_(engine), sku_order_(engine), @@ -358,17 +357,6 @@ void Database::RemoveRecurringTip(const std::string& publisher_key, /** * SERVER PUBLISHER INFO */ -void Database::SearchPublisherPrefixList( - const std::string& publisher_prefix, - SearchPublisherPrefixListCallback callback) { - publisher_prefix_list_.Search(publisher_prefix, std::move(callback)); -} - -void Database::ResetPublisherPrefixList(publisher::PrefixListReader reader, - ResultCallback callback) { - publisher_prefix_list_.Reset(std::move(reader), std::move(callback)); -} - void Database::InsertServerPublisherInfo( const mojom::ServerPublisherInfo& server_info, ResultCallback callback) { diff --git a/components/brave_rewards/core/engine/database/database.h b/components/brave_rewards/core/engine/database/database.h index cdd56793bb5c..4b6cd7151366 100644 --- a/components/brave_rewards/core/engine/database/database.h +++ b/components/brave_rewards/core/engine/database/database.h @@ -26,13 +26,11 @@ #include "brave/components/brave_rewards/core/engine/database/database_initialize.h" #include "brave/components/brave_rewards/core/engine/database/database_media_publisher_info.h" #include "brave/components/brave_rewards/core/engine/database/database_publisher_info.h" -#include "brave/components/brave_rewards/core/engine/database/database_publisher_prefix_list.h" #include "brave/components/brave_rewards/core/engine/database/database_recurring_tip.h" #include "brave/components/brave_rewards/core/engine/database/database_server_publisher_info.h" #include "brave/components/brave_rewards/core/engine/database/database_sku_order.h" #include "brave/components/brave_rewards/core/engine/database/database_sku_transaction.h" #include "brave/components/brave_rewards/core/engine/database/database_unblinded_token.h" -#include "brave/components/brave_rewards/core/engine/publisher/prefix_list_reader.h" #include "brave/components/brave_rewards/core/engine/rewards_callbacks.h" namespace brave_rewards::internal { @@ -232,12 +230,6 @@ class Database { /** * SERVER PUBLISHER INFO */ - void SearchPublisherPrefixList(const std::string& publisher_key, - SearchPublisherPrefixListCallback callback); - - void ResetPublisherPrefixList(publisher::PrefixListReader reader, - ResultCallback callback); - void InsertServerPublisherInfo(const mojom::ServerPublisherInfo& server_info, ResultCallback callback); @@ -317,7 +309,6 @@ class Database { DatabaseExternalTransactions external_transactions_; DatabaseMediaPublisherInfo media_publisher_info_; DatabasePublisherInfo publisher_info_; - DatabasePublisherPrefixList publisher_prefix_list_; DatabaseRecurringTip recurring_tip_; DatabaseServerPublisherInfo server_publisher_info_; DatabaseSKUOrder sku_order_; diff --git a/components/brave_rewards/core/engine/database/database_migration.cc b/components/brave_rewards/core/engine/database/database_migration.cc index e3e112f93924..876a0a83ed22 100644 --- a/components/brave_rewards/core/engine/database/database_migration.cc +++ b/components/brave_rewards/core/engine/database/database_migration.cc @@ -47,6 +47,7 @@ #include "brave/components/brave_rewards/core/engine/database/migration/migration_v39.h" #include "brave/components/brave_rewards/core/engine/database/migration/migration_v4.h" #include "brave/components/brave_rewards/core/engine/database/migration/migration_v40.h" +#include "brave/components/brave_rewards/core/engine/database/migration/migration_v41.h" #include "brave/components/brave_rewards/core/engine/database/migration/migration_v5.h" #include "brave/components/brave_rewards/core/engine/database/migration/migration_v6.h" #include "brave/components/brave_rewards/core/engine/database/migration/migration_v7.h" @@ -140,7 +141,8 @@ void DatabaseMigration::Start(uint32_t table_version, ResultCallback callback) { migration::v37, migration::v38, migration::v39, - migration::v40}; + migration::v40, + migration::v41}; DCHECK_LE(target_version, mappings.size()); diff --git a/components/brave_rewards/core/engine/database/database_migration_unittest.cc b/components/brave_rewards/core/engine/database/database_migration_unittest.cc index c58fcfab01da..e5856d0d2a97 100644 --- a/components/brave_rewards/core/engine/database/database_migration_unittest.cc +++ b/components/brave_rewards/core/engine/database/database_migration_unittest.cc @@ -829,4 +829,11 @@ TEST_F(RewardsDatabaseMigrationTest, Migration_40) { EXPECT_FALSE(GetDB()->DoesTableExist("processed_publisher")); } +TEST_F(RewardsDatabaseMigrationTest, Migration_41) { + DatabaseMigration::SetTargetVersionForTesting(41); + InitializeDatabaseAtVersion(39); + InitializeEngine(); + EXPECT_FALSE(GetDB()->DoesTableExist("publisher_prefix_list")); +} + } // namespace brave_rewards::internal diff --git a/components/brave_rewards/core/engine/database/database_publisher_prefix_list.cc b/components/brave_rewards/core/engine/database/database_publisher_prefix_list.cc deleted file mode 100644 index 2be56ea930ca..000000000000 --- a/components/brave_rewards/core/engine/database/database_publisher_prefix_list.cc +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (c) 2020 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/brave_rewards/core/engine/database/database_publisher_prefix_list.h" - -#include -#include -#include - -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "brave/components/brave_rewards/core/engine/database/database_util.h" -#include "brave/components/brave_rewards/core/engine/publisher/prefix_util.h" -#include "brave/components/brave_rewards/core/engine/rewards_engine.h" - -namespace brave_rewards::internal { - -namespace { - -constexpr char kTableName[] = "publisher_prefix_list"; - -constexpr size_t kHashPrefixSize = 4; -constexpr size_t kMaxInsertRecords = 100'000; - -std::tuple GetPrefixInsertList( - publisher::PrefixIterator begin, - publisher::PrefixIterator end) { - DCHECK(begin != end); - size_t count = 0; - std::string values; - publisher::PrefixIterator iter = begin; - for (iter = begin; iter != end && count < kMaxInsertRecords; - ++count, ++iter) { - auto prefix = *iter; - DCHECK(prefix.size() >= kHashPrefixSize); - std::string hex = base::HexEncode(prefix.data(), kHashPrefixSize); - values.append(base::StringPrintf("(x'%s'),", hex.c_str())); - } - // Remove last comma - if (!values.empty()) { - values.pop_back(); - } - return {iter, std::move(values), count}; -} - -} // namespace - -namespace database { - -DatabasePublisherPrefixList::DatabasePublisherPrefixList(RewardsEngine& engine) - : DatabaseTable(engine) {} - -DatabasePublisherPrefixList::~DatabasePublisherPrefixList() = default; - -void DatabasePublisherPrefixList::Search( - const std::string& publisher_key, - SearchPublisherPrefixListCallback callback) { - std::string hex = - publisher::GetHashPrefixInHex(publisher_key, kHashPrefixSize); - - auto command = mojom::DBCommand::New(); - command->type = mojom::DBCommand::Type::READ; - command->command = base::StringPrintf( - "SELECT EXISTS(SELECT hash_prefix FROM %s WHERE hash_prefix = x'%s')", - kTableName, hex.c_str()); - - command->record_bindings = {mojom::DBCommand::RecordBindingType::BOOL_TYPE}; - - auto transaction = mojom::DBTransaction::New(); - transaction->commands.push_back(std::move(command)); - - engine_->client()->RunDBTransaction( - std::move(transaction), - base::BindOnce(&DatabasePublisherPrefixList::OnSearch, - base::Unretained(this), std::move(callback))); -} - -void DatabasePublisherPrefixList::OnSearch( - SearchPublisherPrefixListCallback callback, - mojom::DBCommandResponsePtr response) { - if (!response || !response->result || - response->status != mojom::DBCommandResponse::Status::RESPONSE_OK || - response->result->get_records().empty()) { - engine_->LogError(FROM_HERE) - << "Unexpected database result while searching publisher prefix list"; - std::move(callback).Run(false); - return; - } - - std::move(callback).Run( - GetBoolColumn(response->result->get_records()[0].get(), 0)); -} - -void DatabasePublisherPrefixList::Reset(publisher::PrefixListReader reader, - ResultCallback callback) { - if (reader_) { - engine_->Log(FROM_HERE) << "Publisher prefix list batch insert in progress"; - std::move(callback).Run(mojom::Result::FAILED); - return; - } - if (reader.empty()) { - engine_->LogError(FROM_HERE) - << "Cannot reset with an empty publisher prefix list"; - std::move(callback).Run(mojom::Result::FAILED); - return; - } - reader_ = std::move(reader); - InsertNext(reader_->begin(), std::move(callback)); -} - -void DatabasePublisherPrefixList::InsertNext(publisher::PrefixIterator begin, - ResultCallback callback) { - DCHECK(reader_ && begin != reader_->end()); - - auto transaction = mojom::DBTransaction::New(); - - if (begin == reader_->begin()) { - engine_->Log(FROM_HERE) << "Clearing publisher prefixes table"; - auto command = mojom::DBCommand::New(); - command->type = mojom::DBCommand::Type::RUN; - command->command = base::StringPrintf("DELETE FROM %s", kTableName); - transaction->commands.push_back(std::move(command)); - } - - auto insert_tuple = GetPrefixInsertList(begin, reader_->end()); - - engine_->Log(FROM_HERE) << "Inserting " << std::get(insert_tuple) - << " records into publisher prefix table"; - - auto command = mojom::DBCommand::New(); - command->type = mojom::DBCommand::Type::RUN; - command->command = base::StringPrintf( - "INSERT OR REPLACE INTO %s (hash_prefix) VALUES %s", kTableName, - std::get(insert_tuple).data()); - - transaction->commands.push_back(std::move(command)); - - engine_->client()->RunDBTransaction( - std::move(transaction), - base::BindOnce(&DatabasePublisherPrefixList::OnInsertNext, - base::Unretained(this), std::move(callback), - std::get(insert_tuple))); -} - -void DatabasePublisherPrefixList::OnInsertNext( - ResultCallback callback, - publisher::PrefixIterator iter, - mojom::DBCommandResponsePtr response) { - if (!response || - response->status != mojom::DBCommandResponse::Status::RESPONSE_OK) { - reader_ = std::nullopt; - std::move(callback).Run(mojom::Result::FAILED); - return; - } - - if (iter == reader_->end()) { - reader_ = std::nullopt; - std::move(callback).Run(mojom::Result::OK); - return; - } - - InsertNext(iter, std::move(callback)); -} - -} // namespace database -} // namespace brave_rewards::internal diff --git a/components/brave_rewards/core/engine/database/database_publisher_prefix_list.h b/components/brave_rewards/core/engine/database/database_publisher_prefix_list.h deleted file mode 100644 index fe9d20bd123c..000000000000 --- a/components/brave_rewards/core/engine/database/database_publisher_prefix_list.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2020 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_BRAVE_REWARDS_CORE_ENGINE_DATABASE_DATABASE_PUBLISHER_PREFIX_LIST_H_ -#define BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_DATABASE_DATABASE_PUBLISHER_PREFIX_LIST_H_ - -#include -#include - -#include "brave/components/brave_rewards/core/engine/database/database_table.h" -#include "brave/components/brave_rewards/core/engine/publisher/prefix_list_reader.h" - -namespace brave_rewards::internal { -namespace database { - -using SearchPublisherPrefixListCallback = base::OnceCallback; - -class DatabasePublisherPrefixList : public DatabaseTable { - public: - explicit DatabasePublisherPrefixList(RewardsEngine& engine); - ~DatabasePublisherPrefixList() override; - - void Reset(publisher::PrefixListReader reader, ResultCallback callback); - - void Search(const std::string& publisher_key, - SearchPublisherPrefixListCallback callback); - - private: - void InsertNext(publisher::PrefixIterator begin, ResultCallback callback); - - void OnSearch(SearchPublisherPrefixListCallback callback, - mojom::DBCommandResponsePtr response); - - void OnInsertNext(ResultCallback callback, - publisher::PrefixIterator iter, - mojom::DBCommandResponsePtr response); - - std::optional reader_; -}; - -} // namespace database -} // namespace brave_rewards::internal - -#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_DATABASE_DATABASE_PUBLISHER_PREFIX_LIST_H_ diff --git a/components/brave_rewards/core/engine/database/database_publisher_prefix_list_unittest.cc b/components/brave_rewards/core/engine/database/database_publisher_prefix_list_unittest.cc deleted file mode 100644 index 34939e2bb325..000000000000 --- a/components/brave_rewards/core/engine/database/database_publisher_prefix_list_unittest.cc +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2020 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/brave_rewards/core/engine/database/database_publisher_prefix_list.h" - -#include -#include -#include -#include - -#include "base/containers/span.h" -#include "base/numerics/byte_conversions.h" -#include "brave/components/brave_rewards/core/engine/publisher/protos/publisher_prefix_list.pb.h" -#include "brave/components/brave_rewards/core/engine/test/rewards_engine_test.h" - -namespace brave_rewards::internal { - -namespace { - -class Client : public TestRewardsEngineClient { - public: - void RunDBTransaction(mojom::DBTransactionPtr transaction, - RunDBTransactionCallback callback) override { - transactions_.push_back(transaction->Clone()); - auto response = mojom::DBCommandResponse::New(); - response->status = mojom::DBCommandResponse::Status::RESPONSE_OK; - std::move(callback).Run(std::move(response)); - } - - std::vector& transactions() { return transactions_; } - - private: - std::vector transactions_; -}; - -} // namespace - -class RewardsDatabasePublisherPrefixListTest : public RewardsEngineTest { - protected: - RewardsDatabasePublisherPrefixListTest() - : RewardsEngineTest(std::make_unique()) {} - - Client& client() { return static_cast(RewardsEngineTest::client()); } - - publisher::PrefixListReader CreateReader(uint32_t prefix_count) { - publisher::PrefixListReader reader; - if (prefix_count == 0) { - return reader; - } - - std::string prefixes; - prefixes.resize(prefix_count * 4); - for (uint32_t i = 0; i < prefix_count; ++i) { - base::as_writable_byte_span(prefixes).subspan(i * 4).first<4>().copy_from( - base::numerics::U32ToBigEndian(i)); - } - - publishers_pb::PublisherPrefixList message; - message.set_prefix_size(4); - message.set_compression_type( - publishers_pb::PublisherPrefixList::NO_COMPRESSION); - message.set_uncompressed_size(prefixes.size()); - message.set_prefixes(std::move(prefixes)); - - std::string out; - message.SerializeToString(&out); - reader.Parse(out); - return reader; - } -}; - -TEST_F(RewardsDatabasePublisherPrefixListTest, Reset) { - database::DatabasePublisherPrefixList prefix_list(engine()); - WaitFor([&](auto callback) { - prefix_list.Reset(CreateReader(100'001), std::move(callback)); - }); - - auto& transactions = client().transactions(); - ASSERT_EQ(transactions.size(), 2ul); - - { - auto& transaction = transactions[0]; - EXPECT_TRUE(transaction); - EXPECT_EQ(transaction->commands.size(), 2u); - EXPECT_EQ(transaction->commands[0]->command, - "DELETE FROM publisher_prefix_list"); - EXPECT_TRUE(transaction->commands[1]->command.starts_with( - "INSERT OR REPLACE INTO publisher_prefix_list (hash_prefix) " - "VALUES (x'00000000'),(x'00000001'),(x'00000002'),")); - } - - { - auto& transaction = transactions[1]; - EXPECT_TRUE(transaction); - EXPECT_EQ(transaction->commands.size(), 1u); - EXPECT_EQ(transaction->commands[0]->command, - "INSERT OR REPLACE INTO publisher_prefix_list (hash_prefix) " - "VALUES (x'000186A0')"); - } -} - -} // namespace brave_rewards::internal diff --git a/components/brave_rewards/core/engine/database/database_util.cc b/components/brave_rewards/core/engine/database/database_util.cc index 102bafe72793..dd84e179a1dc 100644 --- a/components/brave_rewards/core/engine/database/database_util.cc +++ b/components/brave_rewards/core/engine/database/database_util.cc @@ -12,7 +12,7 @@ namespace { -constexpr int kCurrentVersionNumber = 40; +constexpr int kCurrentVersionNumber = 41; constexpr int kCompatibleVersionNumber = 1; } // namespace diff --git a/components/brave_rewards/core/engine/database/migration/migration_v41.h b/components/brave_rewards/core/engine/database/migration/migration_v41.h new file mode 100644 index 000000000000..00c6344d77fa --- /dev/null +++ b/components/brave_rewards/core/engine/database/migration/migration_v41.h @@ -0,0 +1,19 @@ +/* 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_BRAVE_REWARDS_CORE_ENGINE_DATABASE_MIGRATION_MIGRATION_V41_H_ +#define BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_DATABASE_MIGRATION_MIGRATION_V41_H_ + +namespace brave_rewards::internal::database::migration { + +// Migration 41 removes the publisher prefix list table after storage was moved +// to a separate file. +inline constexpr char v41[] = R"sql( + DROP TABLE IF EXISTS publisher_prefix_list; +)sql"; + +} // namespace brave_rewards::internal::database::migration + +#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_DATABASE_MIGRATION_MIGRATION_V41_H_ diff --git a/components/brave_rewards/core/engine/hash_prefix_iterator.h b/components/brave_rewards/core/engine/hash_prefix_iterator.h new file mode 100644 index 000000000000..87993cbc4b27 --- /dev/null +++ b/components/brave_rewards/core/engine/hash_prefix_iterator.h @@ -0,0 +1,115 @@ +/* Copyright (c) 2020 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_BRAVE_REWARDS_CORE_ENGINE_HASH_PREFIX_ITERATOR_H_ +#define BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_HASH_PREFIX_ITERATOR_H_ + +#include +#include + +namespace brave_rewards { + +// A random-access iterator over prefixes stored in an uncompressed prefix list, +// suitable for binary search. +class HashPrefixIterator { + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = std::string_view; + using difference_type = std::ptrdiff_t; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + + HashPrefixIterator(std::string_view data, size_t index, size_t size) + : data_(data), index_(index), size_(size) {} + + HashPrefixIterator(const HashPrefixIterator& rhs) + : data_(rhs.data_), index_(rhs.index_), size_(rhs.size_) {} + + std::string_view operator*() const { return PrefixAt(index_); } + + std::string_view operator[](const int& rhs) const { + return PrefixAt(index_ + rhs); + } + + HashPrefixIterator& operator=(const HashPrefixIterator& rhs) { + index_ = rhs.index_; + return *this; + } + + HashPrefixIterator& operator+=(const int& rhs) { + index_ += rhs; + return *this; + } + + HashPrefixIterator& operator-=(const int& rhs) { + index_ -= rhs; + return *this; + } + + HashPrefixIterator& operator++() { + index_++; + return *this; + } + + HashPrefixIterator& operator--() { + index_--; + return *this; + } + + HashPrefixIterator operator+(const HashPrefixIterator& rhs) const { + return HashPrefixIterator(data_, index_ + rhs.index_, size_); + } + + difference_type operator-(const HashPrefixIterator& rhs) const { + return index_ - rhs.index_; + } + + HashPrefixIterator operator+(const int& rhs) const { + return HashPrefixIterator(data_, index_ + rhs, size_); + } + + HashPrefixIterator operator-(const int& rhs) const { + return HashPrefixIterator(data_, index_ - rhs, size_); + } + + bool operator==(const HashPrefixIterator& rhs) const { + return index_ == rhs.index_; + } + + bool operator!=(const HashPrefixIterator& rhs) const { + return index_ != rhs.index_; + } + + bool operator>(const HashPrefixIterator& rhs) const { + return index_ > rhs.index_; + } + + bool operator<(const HashPrefixIterator& rhs) const { + return index_ < rhs.index_; + } + + bool operator>=(const HashPrefixIterator& rhs) const { + return index_ >= rhs.index_; + } + + bool operator<=(const HashPrefixIterator& rhs) const { + return index_ <= rhs.index_; + } + + private: + std::string_view PrefixAt(size_t index) const { + return data_.substr(index_ * size_, size_); + } + + std::string_view data_; + size_t index_; + size_t size_; +}; + +} // namespace brave_rewards + +#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_HASH_PREFIX_ITERATOR_H_ diff --git a/components/brave_rewards/core/engine/hash_prefix_store.cc b/components/brave_rewards/core/engine/hash_prefix_store.cc new file mode 100644 index 000000000000..bfe1a3eedec3 --- /dev/null +++ b/components/brave_rewards/core/engine/hash_prefix_store.cc @@ -0,0 +1,169 @@ +/* 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/brave_rewards/core/engine/hash_prefix_store.h" + +#include + +#include "base/containers/span.h" +#include "base/containers/span_reader.h" +#include "base/files/file.h" +#include "base/memory/raw_span.h" +#include "base/numerics/byte_conversions.h" +#include "brave/components/brave_rewards/core/engine/hash_prefix_iterator.h" +#include "crypto/sha2.h" + +namespace brave_rewards { + +namespace { + +constexpr uint32_t kFileVersion = 1; +constexpr uint32_t kMinPrefixSize = 4; +constexpr uint32_t kMaxPrefixSize = 32; + +struct FileParts { + uint32_t version = 0; + uint32_t prefix_size = 0; + base::raw_span prefixes; +}; + +bool IsValidFile(const FileParts& parts) { + if (parts.version != kFileVersion) { + return false; + } + if (parts.prefix_size < kMinPrefixSize || + parts.prefix_size > kMaxPrefixSize) { + return false; + } + if (parts.prefixes.size() % parts.prefix_size != 0) { + return false; + } + return true; +} + +std::optional ParseFile(base::span bytes) { + FileParts parts; + base::SpanReader reader(bytes); + if (!reader.ReadU32LittleEndian(parts.version)) { + return std::nullopt; + } + if (!reader.ReadU32LittleEndian(parts.prefix_size)) { + return std::nullopt; + } + parts.prefixes = reader.remaining_span(); + if (!IsValidFile(parts)) { + return std::nullopt; + } + return parts; +} + +} // namespace + +HashPrefixStore::HashPrefixStore(base::FilePath path) + : file_path_(std::move(path)) { + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +HashPrefixStore::~HashPrefixStore() = default; + +bool HashPrefixStore::Open() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (mapped_file_) { + DCHECK(mapped_file_->IsValid()); + return true; + } + + open_called_ = true; + + auto mapped_file = std::make_unique(); + if (!mapped_file->Initialize(file_path_)) { + return false; + } + + auto parts = ParseFile(mapped_file->bytes()); + if (!parts) { + return false; + } + + mapped_file_ = std::move(mapped_file); + prefixes_ = base::as_string_view(parts->prefixes); + prefix_size_ = parts->prefix_size; + + return true; +} + +void HashPrefixStore::Close() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + prefixes_ = {}; + prefix_size_ = 0; + open_called_ = false; + mapped_file_.reset(); +} + +bool HashPrefixStore::UpdatePrefixes(std::string_view prefixes, + size_t prefix_size) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + Close(); + + base::File file; + file.Initialize(file_path_, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + if (!file.IsValid()) { + return false; + } + + auto encoded_version = base::U32ToLittleEndian(kFileVersion); + if (!file.WriteAtCurrentPosAndCheck(base::as_byte_span(encoded_version))) { + return false; + } + + auto encoded_size = + base::U32ToLittleEndian(base::checked_cast(prefix_size)); + if (!file.WriteAtCurrentPosAndCheck(base::as_byte_span(encoded_size))) { + return false; + } + + if (!file.WriteAtCurrentPosAndCheck(base::as_byte_span(prefixes))) { + return false; + } + + file.Close(); + return true; +} + +bool HashPrefixStore::ContainsPrefix(std::string_view value) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!open_called_) { + Open(); + } + + if (prefix_size_ == 0) { + return false; + } + + std::string hash = crypto::SHA256HashString(value); + hash.resize(prefix_size_); + + size_t prefix_count = prefixes_.length() / prefix_size_; + + return std::binary_search( + HashPrefixIterator(prefixes_, 0, prefix_size_), + HashPrefixIterator(prefixes_, prefix_count, prefix_size_), hash); +} + +void HashPrefixStore::UpdatePrefixes(mojom::HashPrefixDataPtr prefix_data, + UpdatePrefixesCallback callback) { + std::move(callback).Run( + UpdatePrefixes(prefix_data->prefixes, prefix_data->prefix_size)); +} + +void HashPrefixStore::ContainsPrefix(const std::string& value, + ContainsPrefixCallback callback) { + std::move(callback).Run(ContainsPrefix(value)); +} + +} // namespace brave_rewards diff --git a/components/brave_rewards/core/engine/hash_prefix_store.h b/components/brave_rewards/core/engine/hash_prefix_store.h new file mode 100644 index 000000000000..23641e4049cb --- /dev/null +++ b/components/brave_rewards/core/engine/hash_prefix_store.h @@ -0,0 +1,63 @@ +/* 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_BRAVE_REWARDS_CORE_ENGINE_HASH_PREFIX_STORE_H_ +#define BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_HASH_PREFIX_STORE_H_ + +#include +#include +#include +#include + +#include "base/files/file_path.h" +#include "base/files/memory_mapped_file.h" +#include "base/sequence_checker.h" +#include "brave/components/brave_rewards/core/mojom/rewards_database.mojom.h" + +namespace brave_rewards { + +// Responsible for storage and retrieval of a sorted hash prefix list. The +// operations of this class will block the current thread on IO. +class HashPrefixStore : public mojom::HashPrefixStore { + public: + explicit HashPrefixStore(base::FilePath path); + ~HashPrefixStore() override; + + HashPrefixStore(const HashPrefixStore&) = delete; + HashPrefixStore& operator=(const HashPrefixStore&) = delete; + + // Opens the hash prefix file, if not already open. + bool Open(); + + // Closes the hash prefix file, if open. + void Close(); + + // Updates the hash prefix file. + bool UpdatePrefixes(std::string_view prefixes, size_t prefix_size); + + // Returns a value indicating if the specified value exists in the prefix + // list. Opens the file if not already open. + bool ContainsPrefix(std::string_view value); + + // mojom::HashPrefixStore: + void UpdatePrefixes(mojom::HashPrefixDataPtr prefix_data, + UpdatePrefixesCallback callback) override; + + void ContainsPrefix(const std::string& value, + ContainsPrefixCallback callback) override; + + private: + base::FilePath file_path_; + std::unique_ptr mapped_file_; + std::string_view prefixes_; + size_t prefix_size_ = 0; + bool open_called_ = false; + + SEQUENCE_CHECKER(sequence_checker_); +}; + +} // namespace brave_rewards + +#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_HASH_PREFIX_STORE_H_ diff --git a/components/brave_rewards/core/engine/hash_prefix_store_unittest.cc b/components/brave_rewards/core/engine/hash_prefix_store_unittest.cc new file mode 100644 index 000000000000..e9347a1fcbce --- /dev/null +++ b/components/brave_rewards/core/engine/hash_prefix_store_unittest.cc @@ -0,0 +1,150 @@ +/* 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/brave_rewards/core/engine/hash_prefix_store.h" + +#include +#include +#include +#include +#include + +#include "base/containers/span_writer.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/numerics/byte_conversions.h" +#include "base/task/sequenced_task_runner.h" +#include "base/test/task_environment.h" +#include "crypto/sha2.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace brave_rewards { + +class RewardsHashPrefixStoreTest : public testing::Test { + public: + void SetUp() override { + Test::SetUp(); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + store_path_ = temp_dir_.GetPath().AppendASCII("prefixes.store"); + } + + void TearDown() override { + base::DeleteFile(store_path_); + Test::TearDown(); + } + + std::array MakeFileHeader(uint32_t version, + uint32_t prefix_size) { + std::array header; + base::SpanWriter writer(base::as_writable_byte_span(header)); + auto encoded_version = base::U32ToLittleEndian(version); + writer.Write(base::as_byte_span(encoded_version)); + auto encoded_size = base::U32ToLittleEndian(prefix_size); + writer.Write(base::as_byte_span(encoded_size)); + return header; + } + + std::string MakePrefixString(size_t prefix_size, + std::vector values) { + std::vector hash_values; + for (auto& value : values) { + std::string hash = crypto::SHA256HashString(value); + hash.resize(prefix_size); + hash_values.push_back(std::move(hash)); + } + + std::sort(hash_values.begin(), hash_values.end()); + + std::string data; + data.reserve(hash_values.size() * prefix_size); + for (auto& value : hash_values) { + data += value; + } + return data; + } + + protected: + base::ScopedTempDir temp_dir_; + base::FilePath store_path_; + base::test::TaskEnvironment task_environment_; +}; + +TEST_F(RewardsHashPrefixStoreTest, FileDoesNotExist) { + HashPrefixStore store(store_path_); + EXPECT_FALSE(store.Open()); + EXPECT_FALSE(store.ContainsPrefix("test-value")); +} + +TEST_F(RewardsHashPrefixStoreTest, EmptyFile) { + base::WriteFile(store_path_, ""); + HashPrefixStore store(store_path_); + EXPECT_FALSE(store.Open()); + EXPECT_FALSE(store.ContainsPrefix("test-value")); +} + +TEST_F(RewardsHashPrefixStoreTest, InvalidFileHeader) { + base::WriteFile(store_path_, "--------"); + HashPrefixStore store(store_path_); + EXPECT_FALSE(store.Open()); + EXPECT_FALSE(store.ContainsPrefix("test-value")); +} + +TEST_F(RewardsHashPrefixStoreTest, InvalidFileVersion) { + auto header = MakeFileHeader(2, 4); + base::WriteFile(store_path_, base::as_byte_span(header)); + HashPrefixStore store(store_path_); + EXPECT_FALSE(store.Open()); +} + +TEST_F(RewardsHashPrefixStoreTest, InvalidPrefixSize) { + auto header = MakeFileHeader(1, 1024); + base::WriteFile(store_path_, base::as_byte_span(header)); + HashPrefixStore store(store_path_); + EXPECT_FALSE(store.Open()); +} + +TEST_F(RewardsHashPrefixStoreTest, InvalidDataLength) { + auto header = MakeFileHeader(1, 4); + auto content = std::string(base::as_string_view(header)) + "?"; + base::WriteFile(store_path_, content); + HashPrefixStore store(store_path_); + EXPECT_FALSE(store.Open()); +} + +TEST_F(RewardsHashPrefixStoreTest, ZeroPrefixes) { + auto header = MakeFileHeader(1, 4); + base::WriteFile(store_path_, base::as_byte_span(header)); + HashPrefixStore store(store_path_); + EXPECT_TRUE(store.Open()); + EXPECT_FALSE(store.ContainsPrefix("test-value")); +} + +TEST_F(RewardsHashPrefixStoreTest, WithPrefixes) { + HashPrefixStore store(store_path_); + + size_t prefix_size = 4; + + std::string data = MakePrefixString( + prefix_size, {"test-value-1", "test-value-2", "test-value-3", + "test-value-4", "test-value-5", "test-value-6", + "test-value-7", "test-value-8", "test-value-9"}); + + bool updated = store.UpdatePrefixes(data, prefix_size); + + EXPECT_TRUE(updated); + EXPECT_TRUE(store.ContainsPrefix("test-value-4")); + EXPECT_TRUE(store.ContainsPrefix("test-value-1")); + EXPECT_TRUE(store.ContainsPrefix("test-value-9")); + EXPECT_FALSE(store.ContainsPrefix("test-value-0")); + + data = MakePrefixString(prefix_size, {"test-value-10"}); + updated = store.UpdatePrefixes(data, prefix_size); + + EXPECT_TRUE(updated); + EXPECT_TRUE(store.ContainsPrefix("test-value-10")); + EXPECT_FALSE(store.ContainsPrefix("test-value-1")); +} + +} // namespace brave_rewards diff --git a/components/brave_rewards/core/engine/publisher/prefix_iterator.h b/components/brave_rewards/core/engine/publisher/prefix_iterator.h deleted file mode 100644 index f69b7508cf84..000000000000 --- a/components/brave_rewards/core/engine/publisher/prefix_iterator.h +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (c) 2020 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/. */ - -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(https://github.com/brave/brave-browser/issues/41661): Remove this and -// convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#ifndef BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_PUBLISHER_PREFIX_ITERATOR_H_ -#define BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_PUBLISHER_PREFIX_ITERATOR_H_ - -#include -#include - -namespace brave_rewards::internal { -namespace publisher { - -// A random-access iterator over prefixes stored in an -// uncompressed prefix list, suitable for binary search -class PrefixIterator { - public: - using iterator_category = std::random_access_iterator_tag; - using value_type = std::string_view; - using difference_type = std::ptrdiff_t; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = value_type*; - using const_pointer = const value_type*; - - PrefixIterator(const char* data, size_t index, size_t size) - : data_(data), index_(index), size_(size) {} - - PrefixIterator(const PrefixIterator& rhs) - : data_(rhs.data_), index_(rhs.index_), size_(rhs.size_) {} - - std::string_view operator*() const { - size_t offset = index_ * size_; - return std::string_view(data_ + offset, size_); - } - - std::string_view operator[](const int& rhs) const { - size_t offset = (index_ + rhs) * size_; - return std::string_view(data_ + offset, size_); - } - - PrefixIterator& operator=(const PrefixIterator& rhs) { - index_ = rhs.index_; - return *this; - } - - PrefixIterator& operator+=(const int& rhs) { - index_ += rhs; - return *this; - } - - PrefixIterator& operator-=(const int& rhs) { - index_ -= rhs; - return *this; - } - - PrefixIterator& operator++() { - index_++; - return *this; - } - - PrefixIterator& operator--() { - index_--; - return *this; - } - - PrefixIterator operator+(const PrefixIterator& rhs) const { - return PrefixIterator(data_, index_ + rhs.index_, size_); - } - - difference_type operator-(const PrefixIterator& rhs) const { - return index_ - rhs.index_; - } - - PrefixIterator operator+(const int& rhs) const { - return PrefixIterator(data_, index_ + rhs, size_); - } - - PrefixIterator operator-(const int& rhs) const { - return PrefixIterator(data_, index_ - rhs, size_); - } - - bool operator==(const PrefixIterator& rhs) const { - return index_ == rhs.index_; - } - - bool operator!=(const PrefixIterator& rhs) const { - return index_ != rhs.index_; - } - - bool operator>(const PrefixIterator& rhs) const { - return index_ > rhs.index_; - } - - bool operator<(const PrefixIterator& rhs) const { - return index_ < rhs.index_; - } - - bool operator>=(const PrefixIterator& rhs) const { - return index_ >= rhs.index_; - } - - bool operator<=(const PrefixIterator& rhs) const { - return index_ <= rhs.index_; - } - - private: - const char* data_; - size_t index_; - size_t size_; -}; - -} // namespace publisher -} // namespace brave_rewards::internal - -#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_PUBLISHER_PREFIX_ITERATOR_H_ diff --git a/components/brave_rewards/core/engine/publisher/prefix_list_reader.cc b/components/brave_rewards/core/engine/publisher/prefix_list_reader.cc index 453c9a76eec1..6d23b26df1a8 100644 --- a/components/brave_rewards/core/engine/publisher/prefix_list_reader.cc +++ b/components/brave_rewards/core/engine/publisher/prefix_list_reader.cc @@ -73,7 +73,7 @@ PrefixListReader::ParseError PrefixListReader::Parse( prefix_size_ = prefix_size; // Perform a quick sanity check that the first few prefixes are in order. - PrefixIterator iter = this->begin(); + HashPrefixIterator iter = this->begin(); if (iter != this->end()) { for (size_t i = 0; i < 5; ++i) { auto next = iter + 1; diff --git a/components/brave_rewards/core/engine/publisher/prefix_list_reader.h b/components/brave_rewards/core/engine/publisher/prefix_list_reader.h index d93ff22cf95f..8cc2915102e3 100644 --- a/components/brave_rewards/core/engine/publisher/prefix_list_reader.h +++ b/components/brave_rewards/core/engine/publisher/prefix_list_reader.h @@ -8,7 +8,7 @@ #include -#include "brave/components/brave_rewards/core/engine/publisher/prefix_iterator.h" +#include "brave/components/brave_rewards/core/engine/hash_prefix_iterator.h" namespace brave_rewards::internal { namespace publisher { @@ -42,15 +42,21 @@ class PrefixListReader { ParseError Parse(const std::string& contents); // Returns an iterator pointing to the first prefix in the list - PrefixIterator begin() const { - return PrefixIterator(prefixes_.data(), 0, prefix_size_); + HashPrefixIterator begin() const { + return HashPrefixIterator(prefixes_, 0, prefix_size_); } // Returns an iterator pointing to the past-the-end element in the list - PrefixIterator end() const { - return PrefixIterator(prefixes_.data(), size(), prefix_size_); + HashPrefixIterator end() const { + return HashPrefixIterator(prefixes_, size(), prefix_size_); } + // Returns the hash prefix size. + size_t prefix_size() const { return prefix_size_; } + + // Returns the entire raw prefix list. + const std::string& prefixes() const { return prefixes_; } + // Returns the number of prefixes in the list size_t size() const { return prefixes_.size() / prefix_size_; } diff --git a/components/brave_rewards/core/engine/publisher/publisher.cc b/components/brave_rewards/core/engine/publisher/publisher.cc index 9beeee9eb3ca..352b1867f84e 100644 --- a/components/brave_rewards/core/engine/publisher/publisher.cc +++ b/components/brave_rewards/core/engine/publisher/publisher.cc @@ -145,7 +145,7 @@ void Publisher::SaveVisit(const std::string& publisher_key, weak_factory_.GetWeakPtr(), publisher_key, visit_data, duration, first_visit, window_id, std::move(callback)); - engine_->database()->SearchPublisherPrefixList( + engine_->client()->CreatorPrefixStoreContains( publisher_key, base::BindOnce(&Publisher::OnSearchPrefixListForSaveVisit, weak_factory_.GetWeakPtr(), publisher_key, std::move(on_server_info))); @@ -682,7 +682,7 @@ void Publisher::OnServerPublisherInfoLoaded( // If we don't have a record in the database for this publisher, search the // prefix list. If the prefix list indicates that the publisher is likely // registered, then fetch the publisher data. - engine_->database()->SearchPublisherPrefixList( + engine_->client()->CreatorPrefixStoreContains( publisher_key, base::BindOnce(&Publisher::OnSearchPrefixListForGetServerPublisherInfo, weak_factory_.GetWeakPtr(), publisher_key, diff --git a/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.cc b/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.cc index 69c1d4096dec..c0c24d746722 100644 --- a/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.cc +++ b/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.cc @@ -90,14 +90,18 @@ void PublisherPrefixListUpdater::OnFetchCompleted(mojom::Result result, retry_count_ = 0; - engine_->Log(FROM_HERE) << "Resetting publisher prefix list table"; - engine_->database()->ResetPublisherPrefixList( - std::move(reader), + auto prefix_data = mojom::HashPrefixData::New(); + prefix_data->prefixes = reader.prefixes(); + prefix_data->prefix_size = reader.prefix_size(); + + engine_->Log(FROM_HERE) << "Resetting publisher prefix list store"; + engine_->client()->UpdateCreatorPrefixStore( + std::move(prefix_data), base::BindOnce(&PublisherPrefixListUpdater::OnPrefixListInserted, weak_factory_.GetWeakPtr())); } -void PublisherPrefixListUpdater::OnPrefixListInserted(mojom::Result result) { +void PublisherPrefixListUpdater::OnPrefixListInserted(bool success) { // At this point we have received a valid response from the server // and we've attempted to insert it into the database. Store the last // successful fetch time for calculation of next refresh interval. @@ -109,9 +113,8 @@ void PublisherPrefixListUpdater::OnPrefixListInserted(mojom::Result result) { StartFetchTimer(FROM_HERE, GetAutoUpdateDelay()); } - if (result != mojom::Result::OK) { - engine_->LogError(FROM_HERE) - << "Error updating publisher prefix list table: " << result; + if (!success) { + engine_->LogError(FROM_HERE) << "Error updating publisher prefix list"; return; } diff --git a/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.h b/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.h index c5f0f4fdffba..9acdcdd6ae35 100644 --- a/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.h +++ b/components/brave_rewards/core/engine/publisher/publisher_prefix_list_updater.h @@ -55,7 +55,7 @@ class PublisherPrefixListUpdater { void OnFetchTimerElapsed(); void OnFetchCompleted(mojom::Result result, std::string body); - void OnPrefixListInserted(mojom::Result result); + void OnPrefixListInserted(bool success); base::TimeDelta GetAutoUpdateDelay(); base::TimeDelta GetRetryAfterFailureDelay(); diff --git a/components/brave_rewards/core/engine/publisher/publisher_status_helper.cc b/components/brave_rewards/core/engine/publisher/publisher_status_helper.cc index 1c44bb1b01d8..caf5e237c8f8 100644 --- a/components/brave_rewards/core/engine/publisher/publisher_status_helper.cc +++ b/components/brave_rewards/core/engine/publisher/publisher_status_helper.cc @@ -90,7 +90,7 @@ void RefreshNext(std::unique_ptr task_info) { // Look for publisher key in hash index. auto& key = task_info->current->first; - task_info->engine->database()->SearchPublisherPrefixList( + task_info->engine->client()->CreatorPrefixStoreContains( key, base::BindOnce(on_prefix_searched, std::move(task_info))); } diff --git a/components/brave_rewards/core/engine/state/state_migration.cc b/components/brave_rewards/core/engine/state/state_migration.cc index edcdb3cb2a12..5e28acde1093 100644 --- a/components/brave_rewards/core/engine/state/state_migration.cc +++ b/components/brave_rewards/core/engine/state/state_migration.cc @@ -12,7 +12,7 @@ namespace { -constexpr int kCurrentVersionNumber = 14; +constexpr int kCurrentVersionNumber = 15; } // namespace @@ -31,7 +31,8 @@ StateMigration::StateMigration(RewardsEngine& engine) v11_(engine), v12_(engine), v13_(engine), - v14_(engine) {} + v14_(engine), + v15_(engine) {} StateMigration::~StateMigration() = default; @@ -129,6 +130,10 @@ void StateMigration::Migrate(ResultCallback callback) { v14_.Migrate(std::move(migrate_callback)); return; } + case 15: { + v15_.Migrate(std::move(migrate_callback)); + return; + } } engine_->LogError(FROM_HERE) diff --git a/components/brave_rewards/core/engine/state/state_migration.h b/components/brave_rewards/core/engine/state/state_migration.h index 0a993cab7971..1f2d1ea90a80 100644 --- a/components/brave_rewards/core/engine/state/state_migration.h +++ b/components/brave_rewards/core/engine/state/state_migration.h @@ -14,6 +14,7 @@ #include "brave/components/brave_rewards/core/engine/state/state_migration_v12.h" #include "brave/components/brave_rewards/core/engine/state/state_migration_v13.h" #include "brave/components/brave_rewards/core/engine/state/state_migration_v14.h" +#include "brave/components/brave_rewards/core/engine/state/state_migration_v15.h" #include "brave/components/brave_rewards/core/engine/state/state_migration_v2.h" #include "brave/components/brave_rewards/core/engine/state/state_migration_v3.h" #include "brave/components/brave_rewards/core/engine/state/state_migration_v4.h" @@ -57,6 +58,7 @@ class StateMigration { StateMigrationV12 v12_; StateMigrationV13 v13_; StateMigrationV14 v14_; + StateMigrationV15 v15_; }; } // namespace state diff --git a/components/brave_rewards/core/engine/state/state_migration_v15.cc b/components/brave_rewards/core/engine/state/state_migration_v15.cc new file mode 100644 index 000000000000..23e17b8dbe16 --- /dev/null +++ b/components/brave_rewards/core/engine/state/state_migration_v15.cc @@ -0,0 +1,24 @@ +/* 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/brave_rewards/core/engine/state/state_migration_v15.h" + +#include + +#include "brave/components/brave_rewards/core/engine/rewards_engine.h" +#include "brave/components/brave_rewards/core/engine/state/state_keys.h" + +namespace brave_rewards::internal::state { + +StateMigrationV15::StateMigrationV15(RewardsEngine& engine) : engine_(engine) {} + +StateMigrationV15::~StateMigrationV15() = default; + +void StateMigrationV15::Migrate(ResultCallback callback) { + engine_->SetState(kServerPublisherListStamp, 0); + std::move(callback).Run(mojom::Result::OK); +} + +} // namespace brave_rewards::internal::state diff --git a/components/brave_rewards/core/engine/state/state_migration_v15.h b/components/brave_rewards/core/engine/state/state_migration_v15.h new file mode 100644 index 000000000000..53f46ab53cbb --- /dev/null +++ b/components/brave_rewards/core/engine/state/state_migration_v15.h @@ -0,0 +1,33 @@ +/* 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_BRAVE_REWARDS_CORE_ENGINE_STATE_STATE_MIGRATION_V15_H_ +#define BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_STATE_STATE_MIGRATION_V15_H_ + +#include "base/memory/raw_ref.h" +#include "brave/components/brave_rewards/core/engine/rewards_callbacks.h" + +namespace brave_rewards::internal { +class RewardsEngine; + +namespace state { + +// Migration 15 resets the `kServerPublisherListStamp` pref in order to trigger +// a download of the creator hash prefix list. +class StateMigrationV15 { + public: + explicit StateMigrationV15(RewardsEngine& engine); + ~StateMigrationV15(); + + void Migrate(ResultCallback); + + private: + const raw_ref engine_; +}; + +} // namespace state +} // namespace brave_rewards::internal + +#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_ENGINE_STATE_STATE_MIGRATION_V15_H_ diff --git a/components/brave_rewards/core/engine/test/BUILD.gn b/components/brave_rewards/core/engine/test/BUILD.gn index f2ae68501451..03776bd4668b 100644 --- a/components/brave_rewards/core/engine/test/BUILD.gn +++ b/components/brave_rewards/core/engine/test/BUILD.gn @@ -16,7 +16,6 @@ source_set("test") { "//brave/components/brave_rewards/core/engine/database/database_migration_unittest.cc", "//brave/components/brave_rewards/core/engine/database/database_mock.cc", "//brave/components/brave_rewards/core/engine/database/database_mock.h", - "//brave/components/brave_rewards/core/engine/database/database_publisher_prefix_list_unittest.cc", "//brave/components/brave_rewards/core/engine/database/database_util_unittest.cc", "//brave/components/brave_rewards/core/engine/endpoint/bitflyer/get_balance/get_balance_bitflyer_unittest.cc", "//brave/components/brave_rewards/core/engine/endpoint/bitflyer/post_oauth/post_oauth_bitflyer_unittest.cc", @@ -53,6 +52,7 @@ source_set("test") { "//brave/components/brave_rewards/core/engine/endpoints/uphold/post_oauth_uphold_unittest.cc", "//brave/components/brave_rewards/core/engine/endpoints/zebpay/get_balance_zebpay_unittest.cc", "//brave/components/brave_rewards/core/engine/endpoints/zebpay/post_oauth_zebpay_unittest.cc", + "//brave/components/brave_rewards/core/engine/hash_prefix_store_unittest.cc", "//brave/components/brave_rewards/core/engine/legacy/bat_util_unittest.cc", "//brave/components/brave_rewards/core/engine/legacy/client_state_unittest.cc", "//brave/components/brave_rewards/core/engine/legacy/publisher_settings_state_unittest.cc", diff --git a/components/brave_rewards/core/engine/test/data/publisher_info_schema_current.txt b/components/brave_rewards/core/engine/test/data/publisher_info_schema_current.txt index 87e290839a44..b6989f9f9a8a 100644 --- a/components/brave_rewards/core/engine/test/data/publisher_info_schema_current.txt +++ b/components/brave_rewards/core/engine/test/data/publisher_info_schema_current.txt @@ -28,7 +28,6 @@ index|sqlite_autoindex_media_publisher_info_1|media_publisher_info| index|sqlite_autoindex_meta_1|meta| index|sqlite_autoindex_promotion_1|promotion| index|sqlite_autoindex_publisher_info_1|publisher_info| -index|sqlite_autoindex_publisher_prefix_list_1|publisher_prefix_list| index|sqlite_autoindex_recurring_donation_1|recurring_donation| index|sqlite_autoindex_server_publisher_banner_1|server_publisher_banner| index|sqlite_autoindex_server_publisher_info_1|server_publisher_info| @@ -52,7 +51,6 @@ table|media_publisher_info|media_publisher_info|CREATE TABLE media_publisher_inf table|meta|meta|CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR) table|promotion|promotion|CREATE TABLE promotion ( promotion_id TEXT NOT NULL, version INTEGER NOT NULL, type INTEGER NOT NULL, public_keys TEXT NOT NULL, suggestions INTEGER NOT NULL DEFAULT 0, approximate_value DOUBLE NOT NULL DEFAULT 0, status INTEGER NOT NULL DEFAULT 0, expires_at TIMESTAMP NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, claimed_at TIMESTAMP, claim_id TEXT, legacy BOOLEAN DEFAULT 0 NOT NULL, claimable_until INTEGER, PRIMARY KEY (promotion_id) ) table|publisher_info|publisher_info|CREATE TABLE publisher_info ( publisher_id LONGVARCHAR PRIMARY KEY NOT NULL UNIQUE, excluded INTEGER DEFAULT 0 NOT NULL, name TEXT NOT NULL, favIcon TEXT NOT NULL, url TEXT NOT NULL, provider TEXT NOT NULL ) -table|publisher_prefix_list|publisher_prefix_list|CREATE TABLE publisher_prefix_list (hash_prefix BLOB PRIMARY KEY NOT NULL) table|recurring_donation|recurring_donation|CREATE TABLE recurring_donation ( publisher_id LONGVARCHAR NOT NULL PRIMARY KEY UNIQUE, amount DOUBLE DEFAULT 0 NOT NULL, added_date INTEGER DEFAULT 0 NOT NULL , next_contribution_at TIMESTAMP) table|server_publisher_banner|server_publisher_banner|CREATE TABLE server_publisher_banner ( publisher_key LONGVARCHAR PRIMARY KEY NOT NULL UNIQUE, title TEXT, description TEXT, background TEXT, logo TEXT , web3_url TEXT) table|server_publisher_info|server_publisher_info|CREATE TABLE server_publisher_info ( publisher_key LONGVARCHAR PRIMARY KEY NOT NULL, status INTEGER DEFAULT 0 NOT NULL, address TEXT NOT NULL, updated_at TIMESTAMP NOT NULL ) diff --git a/components/brave_rewards/core/engine/test/test_rewards_engine_client.cc b/components/brave_rewards/core/engine/test/test_rewards_engine_client.cc index a0eee5d47b67..cd06359e5c17 100644 --- a/components/brave_rewards/core/engine/test/test_rewards_engine_client.cc +++ b/components/brave_rewards/core/engine/test/test_rewards_engine_client.cc @@ -328,6 +328,18 @@ void TestRewardsEngineClient::RunDBTransaction( std::move(callback).Run(std::move(response)); } +void TestRewardsEngineClient::UpdateCreatorPrefixStore( + mojom::HashPrefixDataPtr prefix_data, + UpdateCreatorPrefixStoreCallback callback) { + std::move(callback).Run(false); +} + +void TestRewardsEngineClient::CreatorPrefixStoreContains( + const std::string& value, + CreatorPrefixStoreContainsCallback callback) { + std::move(callback).Run(false); +} + void TestRewardsEngineClient::Log(const std::string& file, int32_t line, int32_t verbose_level, diff --git a/components/brave_rewards/core/engine/test/test_rewards_engine_client.h b/components/brave_rewards/core/engine/test/test_rewards_engine_client.h index cfc82479becb..8a340bdc94a9 100644 --- a/components/brave_rewards/core/engine/test/test_rewards_engine_client.h +++ b/components/brave_rewards/core/engine/test/test_rewards_engine_client.h @@ -173,6 +173,14 @@ class TestRewardsEngineClient : public mojom::RewardsEngineClient { void RunDBTransaction(mojom::DBTransactionPtr transaction, RunDBTransactionCallback callback) override; + void UpdateCreatorPrefixStore( + mojom::HashPrefixDataPtr prefix_data, + UpdateCreatorPrefixStoreCallback callback) override; + + void CreatorPrefixStoreContains( + const std::string& value, + CreatorPrefixStoreContainsCallback callback) override; + void Log(const std::string& file, int32_t line, int32_t verbose_level, diff --git a/components/brave_rewards/core/mojom/rewards_database.mojom b/components/brave_rewards/core/mojom/rewards_database.mojom index edaa8b830166..b3468ffdecd3 100644 --- a/components/brave_rewards/core/mojom/rewards_database.mojom +++ b/components/brave_rewards/core/mojom/rewards_database.mojom @@ -71,3 +71,17 @@ struct DBCommandResponse { DBCommandResult? result; Status status; }; + +interface RewardsDatabase { + RunDBTransaction(DBTransaction transaction) => (DBCommandResponse response); +}; + +struct HashPrefixData { + string prefixes; + uint32 prefix_size; +}; + +interface HashPrefixStore { + UpdatePrefixes(HashPrefixData prefix_data) => (bool success); + ContainsPrefix(string value) => (bool contains_prefix); +}; diff --git a/components/brave_rewards/core/mojom/rewards_engine.mojom b/components/brave_rewards/core/mojom/rewards_engine.mojom index 09b416de4e3b..713f57ae4a97 100644 --- a/components/brave_rewards/core/mojom/rewards_engine.mojom +++ b/components/brave_rewards/core/mojom/rewards_engine.mojom @@ -207,6 +207,10 @@ interface RewardsEngineClient { RunDBTransaction(DBTransaction transaction) => (DBCommandResponse response); + UpdateCreatorPrefixStore(HashPrefixData prefix_data) => (bool success); + + CreatorPrefixStoreContains(string value) => (bool contains_prefix); + Log(string file, int32 line, int32 verbose_level, string message); ClearAllNotifications(); diff --git a/components/brave_rewards/core/remote_worker.h b/components/brave_rewards/core/remote_worker.h new file mode 100644 index 000000000000..5464fc6965e1 --- /dev/null +++ b/components/brave_rewards/core/remote_worker.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2024 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_BRAVE_REWARDS_CORE_REMOTE_WORKER_H_ +#define BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_REMOTE_WORKER_H_ + +#include +#include +#include + +#include "base/memory/scoped_refptr.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" + +namespace base { +class SequencedTaskRunner; +} + +namespace brave_rewards { + +// Schedules the creation of an interface implementation on a worker sequence +// and binds a pending remote to it. The implementation's lifetime is tied to +// the lifetime of the message pipe. When the pipe is reset, the implementation +// will be destroyed on the worker sequence. +template + requires(std::is_base_of_v) +void CreateRemoteWorker(scoped_refptr task_runner, + mojo::PendingReceiver pending_receiver, + Args&&... args) { + auto create_on_worker = [](mojo::PendingReceiver pending_receiver, + std::decay_t... args) { + if (pending_receiver) { + mojo::MakeSelfOwnedReceiver( + std::make_unique(std::forward(args)...), + std::move(pending_receiver)); + } + }; + + task_runner->PostTask( + FROM_HERE, base::BindOnce(create_on_worker, std::move(pending_receiver), + std::forward(args)...)); +} + +// A convenience wrapper around mojo::Remote that allows running a Mojo +// interface implementation on a worker sequence. +template +class RemoteWorker { + public: + explicit RemoteWorker(scoped_refptr task_runner) + : task_runner_(task_runner) {} + + ~RemoteWorker() = default; + + auto operator->() const { return remote_.get(); } + + bool is_bound() const { return remote_.is_bound(); } + + void reset() { remote_.reset(); } + + // Schedules the creation of an interface implementation on the worker + // sequence and binds the remote. The implementation's lifetime is tied to + // the lifetime of the message pipe. When the pipe is reset, or this object is + // destroyed, the implementation will be destroyed on the worker sequence. + template + requires(std::is_base_of_v) + void BindRemote(Args&&... args) { + remote_.reset(); + CreateRemoteWorker(task_runner_, remote_.BindNewPipeAndPassReceiver(), + std::forward(args)...); + } + + private: + mojo::Remote remote_; + scoped_refptr task_runner_; +}; + +} // namespace brave_rewards + +#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_CORE_REMOTE_WORKER_H_ diff --git a/ios/browser/api/brave_rewards/brave_rewards_api.mm b/ios/browser/api/brave_rewards/brave_rewards_api.mm index e01d68ca30aa..dd57b269301d 100644 --- a/ios/browser/api/brave_rewards/brave_rewards_api.mm +++ b/ios/browser/api/brave_rewards/brave_rewards_api.mm @@ -24,8 +24,10 @@ #include "base/values.h" #include "brave/build/ios/mojom/cpp_transformations.h" #include "brave/components/brave_rewards/core/engine/global_constants.h" +#include "brave/components/brave_rewards/core/engine/hash_prefix_store.h" #include "brave/components/brave_rewards/core/engine/rewards_database.h" #include "brave/components/brave_rewards/core/engine/rewards_engine.h" +#include "brave/components/brave_rewards/core/remote_worker.h" #include "brave/components/brave_rewards/core/rewards_flags.h" #import "brave/ios/browser/api/brave_rewards/rewards.mojom.objc+private.h" #import "brave/ios/browser/api/brave_rewards/rewards_client_bridge.h" @@ -42,6 +44,26 @@ #error "This file requires ARC support." #endif +namespace { + +using brave_rewards::RemoteWorker; + +class HashPrefixStoreWorker + : public RemoteWorker { + public: + HashPrefixStoreWorker() : RemoteWorker(CreateTaskRunner()) {} + ~HashPrefixStoreWorker() = default; + + private: + static scoped_refptr CreateTaskRunner() { + return base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); + } +}; + +} // namespace + namespace brave_rewards::internal { template @@ -106,6 +128,7 @@ @interface BraveRewardsAPI () { base::SequenceBound rewardsDatabase; scoped_refptr databaseQueue; scoped_refptr _engineTaskRunner; + HashPrefixStoreWorker _creatorPrefixStore; } @property(nonatomic, copy) NSString* storagePath; @@ -172,6 +195,9 @@ - (instancetype)initWithStateStoragePath:(NSString*)path { base::SequenceBound( databaseQueue, base::FilePath(dbPath)); + _creatorPrefixStore.BindRemote( + base::FilePath([self creatorPrefixStorePath].UTF8String)); + _engineTaskRunner->PostTask( FROM_HERE, base::BindOnce(^{ self->_rewardsClient = @@ -266,6 +292,11 @@ - (NSString*)rewardsDatabasePath { return [self.storagePath stringByAppendingPathComponent:@"Rewards.db"]; } +- (NSString*)creatorPrefixStorePath { + return + [self.storagePath stringByAppendingPathComponent:@"RewardsCreators.db"]; +} + - (void)resetRewardsDatabase { const auto dbPath = [self rewardsDatabasePath]; [NSFileManager.defaultManager removeItemAtPath:dbPath error:nil]; @@ -275,6 +306,11 @@ - (void)resetRewardsDatabase { rewardsDatabase = base::SequenceBound( databaseQueue, base::FilePath(base::SysNSStringToUTF8(dbPath))); + + const auto prefixPath = [self creatorPrefixStorePath]; + [NSFileManager.defaultManager removeItemAtPath:prefixPath error:nil]; + _creatorPrefixStore.BindRemote( + base::FilePath(base::SysNSStringToUTF8(prefixPath))); } - (NSString*)randomStatePath { @@ -1024,6 +1060,22 @@ - (void)runDbTransaction:(brave_rewards::mojom::DBTransactionPtr)transaction std::move(callback))); } +- (void)updateCreatorPrefixStore: + (brave_rewards::mojom::HashPrefixDataPtr)prefix_data + callback: + (brave_rewards::mojom::RewardsEngineClient:: + UpdateCreatorPrefixStoreCallback)callback { + _creatorPrefixStore->UpdatePrefixes(std::move(prefix_data), + std::move(callback)); +} + +- (void)creatorPrefixStoreContains:(const std::string&)value + callback: + (brave_rewards::mojom::RewardsEngineClient:: + CreatorPrefixStoreContainsCallback)callback { + _creatorPrefixStore->ContainsPrefix(value, std::move(callback)); +} + - (void)walletDisconnected:(const std::string&)wallet_type { // Not used on iOS } diff --git a/ios/browser/api/brave_rewards/rewards_client_bridge.h b/ios/browser/api/brave_rewards/rewards_client_bridge.h index f6acb57c8aff..5733bb85c658 100644 --- a/ios/browser/api/brave_rewards/rewards_client_bridge.h +++ b/ios/browser/api/brave_rewards/rewards_client_bridge.h @@ -139,6 +139,14 @@ NS_ASSUME_NONNULL_BEGIN - (void)runDbTransaction:(brave_rewards::mojom::DBTransactionPtr)transaction callback:(brave_rewards::mojom::RewardsEngineClient:: RunDBTransactionCallback)callback; +- (void)updateCreatorPrefixStore: + (brave_rewards::mojom::HashPrefixDataPtr)prefix_data + callback:(brave_rewards::mojom::RewardsEngineClient:: + UpdateCreatorPrefixStoreCallback)callback; +- (void)creatorPrefixStoreContains:(const std::string&)value + callback: + (brave_rewards::mojom::RewardsEngineClient:: + CreatorPrefixStoreContainsCallback)callback; - (void)log:(const std::string&)file line:(int32_t)line verboseLevel:(int32_t)verboseLevel diff --git a/ios/browser/api/brave_rewards/rewards_client_ios.h b/ios/browser/api/brave_rewards/rewards_client_ios.h index e9987f904e6d..450452bcc1e7 100644 --- a/ios/browser/api/brave_rewards/rewards_client_ios.h +++ b/ios/browser/api/brave_rewards/rewards_client_ios.h @@ -106,6 +106,12 @@ class RewardsClientIOS : public brave_rewards::mojom::RewardsEngineClient { void ReconcileStampReset() override; void RunDBTransaction(brave_rewards::mojom::DBTransactionPtr transaction, RunDBTransactionCallback callback) override; + void UpdateCreatorPrefixStore( + brave_rewards::mojom::HashPrefixDataPtr prefix_data, + UpdateCreatorPrefixStoreCallback callback) override; + void CreatorPrefixStoreContains( + const std::string& value, + CreatorPrefixStoreContainsCallback callback) override; void ClearAllNotifications() override; void ExternalWalletConnected() override; void ExternalWalletLoggedOut() override; diff --git a/ios/browser/api/brave_rewards/rewards_client_ios.mm b/ios/browser/api/brave_rewards/rewards_client_ios.mm index 8cd50165505a..a9ae8cb2e99c 100644 --- a/ios/browser/api/brave_rewards/rewards_client_ios.mm +++ b/ios/browser/api/brave_rewards/rewards_client_ios.mm @@ -180,6 +180,17 @@ [bridge_ runDbTransaction:std::move(transaction) callback:std::move(callback)]; } +void RewardsClientIOS::UpdateCreatorPrefixStore( + brave_rewards::mojom::HashPrefixDataPtr prefix_data, + UpdateCreatorPrefixStoreCallback callback) { + [bridge_ updateCreatorPrefixStore:std::move(prefix_data) + callback:std::move(callback)]; +} +void RewardsClientIOS::CreatorPrefixStoreContains( + const std::string& value, + CreatorPrefixStoreContainsCallback callback) { + [bridge_ creatorPrefixStoreContains:value callback:std::move(callback)]; +} void RewardsClientIOS::ClearAllNotifications() { [bridge_ clearAllNotifications]; }