[ads] Add SmartNTT virtual prefs support on iOS (#29161)
* [ads] Add SmartNTT virtual prefs support on iOS * [ads] Add SmartNTT virtual prefs tests * Fix review comments
This commit is contained in:
@@ -11,6 +11,7 @@ source_set("brave_ads") {
|
||||
"ads_service_delegate.h",
|
||||
"ads_service_factory.h",
|
||||
"analytics/p3a/brave_stats_helper.h",
|
||||
"virtual_pref_provider_delegate.h",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
@@ -47,6 +48,7 @@ source_set("impl") {
|
||||
"application_state/notification_helper/notification_helper.h",
|
||||
"application_state/notification_helper/notification_helper_impl.cc",
|
||||
"application_state/notification_helper/notification_helper_impl.h",
|
||||
"virtual_pref_provider_delegate.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@@ -63,7 +65,6 @@ source_set("impl") {
|
||||
"//brave/components/brave_adaptive_captcha",
|
||||
"//brave/components/brave_ads/browser/application_state",
|
||||
"//brave/components/p3a_utils",
|
||||
"//brave/components/skus/browser",
|
||||
"//chrome/browser:browser_process",
|
||||
"//chrome/browser:browser_public_dependencies",
|
||||
"//chrome/browser:primitives",
|
||||
|
||||
@@ -5,31 +5,17 @@
|
||||
|
||||
#include "brave/browser/brave_ads/ads_service_delegate.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/check_deref.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/version.h"
|
||||
#include "base/version_info/channel.h"
|
||||
#include "base/version_info/version_info.h"
|
||||
#include "brave/browser/brave_ads/ad_units/notification_ad/notification_ad_platform_bridge.h"
|
||||
#include "brave/browser/brave_ads/application_state/notification_helper/notification_helper.h"
|
||||
#include "brave/browser/ui/brave_ads/notification_ad.h"
|
||||
#include "brave/components/brave_adaptive_captcha/brave_adaptive_captcha_service.h"
|
||||
#include "brave/components/brave_ads/core/public/common/locale/locale_util.h"
|
||||
#include "brave/components/skus/browser/pref_names.h"
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/browser/notifications/notification_display_service.h"
|
||||
#include "chrome/browser/notifications/notification_display_service_factory.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/search_engines/template_url_prepopulate_data_resolver_factory.h"
|
||||
#include "chrome/common/channel_info.h"
|
||||
#include "components/search_engines/template_url_data.h"
|
||||
#include "components/search_engines/template_url_prepopulate_data.h"
|
||||
#include "components/search_engines/template_url_prepopulate_data_resolver.h"
|
||||
#include "ui/message_center/public/cpp/notification.h"
|
||||
#include "ui/message_center/public/cpp/notification_types.h"
|
||||
#include "ui/message_center/public/cpp/notifier_id.h"
|
||||
@@ -48,102 +34,7 @@
|
||||
namespace brave_ads {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kSkuEnvironmentPrefix[] = "skus:";
|
||||
constexpr char kSkuOrdersKey[] = "orders";
|
||||
constexpr char kSkuOrderLocationKey[] = "location";
|
||||
constexpr char kSkuOrderCreatedAtKey[] = "created_at";
|
||||
constexpr char kSkuOrderExpiresAtKey[] = "expires_at";
|
||||
constexpr char kSkuOrderLastPaidAtKey[] = "last_paid_at";
|
||||
constexpr char kSkuOrderStatusKey[] = "status";
|
||||
constexpr char kNotificationAdUrlPrefix[] = "https://www.brave.com/ads/?";
|
||||
|
||||
int GetVersionComponent(size_t index) {
|
||||
const base::Version& version = version_info::GetVersion();
|
||||
const std::vector<uint32_t>& version_components = version.components();
|
||||
return index < version_components.size()
|
||||
? static_cast<int>(version_components[index])
|
||||
: 0;
|
||||
}
|
||||
|
||||
int GetMajorVersion() {
|
||||
return GetVersionComponent(0);
|
||||
}
|
||||
|
||||
int GetMinorVersion() {
|
||||
return GetVersionComponent(1);
|
||||
}
|
||||
|
||||
int GetBuildVersion() {
|
||||
return GetVersionComponent(2);
|
||||
}
|
||||
|
||||
int GetPatchVersion() {
|
||||
return GetVersionComponent(3);
|
||||
}
|
||||
|
||||
bool IsMobilePlatform() {
|
||||
std::string_view operating_system_name = version_info::GetOSType();
|
||||
return operating_system_name == "Android" || operating_system_name == "iOS";
|
||||
}
|
||||
|
||||
std::string StripSkuEnvironmentPrefix(const std::string& environment) {
|
||||
const size_t pos = environment.find(':');
|
||||
return environment.substr(pos + 1);
|
||||
}
|
||||
|
||||
std::string NormalizeSkuStatus(const std::string& status) {
|
||||
// Normalize the status field to use consistent (US) spelling, as the JSON
|
||||
// source localizes it (e.g., "cancelled" vs "canceled").
|
||||
return status == "cancelled" ? "canceled" : status;
|
||||
}
|
||||
|
||||
base::Value::Dict ParseSkuOrder(const base::Value::Dict& dict) {
|
||||
base::Value::Dict order;
|
||||
|
||||
if (const std::string* const created_at =
|
||||
dict.FindString(kSkuOrderCreatedAtKey)) {
|
||||
order.Set(kSkuOrderCreatedAtKey, *created_at);
|
||||
}
|
||||
|
||||
if (const std::string* const expires_at =
|
||||
dict.FindString(kSkuOrderExpiresAtKey)) {
|
||||
order.Set(kSkuOrderExpiresAtKey, *expires_at);
|
||||
}
|
||||
|
||||
if (const std::string* const last_paid_at =
|
||||
dict.FindString(kSkuOrderLastPaidAtKey)) {
|
||||
order.Set(kSkuOrderLastPaidAtKey, *last_paid_at);
|
||||
}
|
||||
|
||||
if (const std::string* const status = dict.FindString(kSkuOrderStatusKey)) {
|
||||
const std::string normalized_status = NormalizeSkuStatus(*status);
|
||||
order.Set(kSkuOrderStatusKey, normalized_status);
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
base::Value::Dict ParseSkuOrders(const base::Value::Dict& dict) {
|
||||
base::Value::Dict orders;
|
||||
|
||||
for (const auto [/*id*/ _, value] : dict) {
|
||||
const base::Value::Dict* const order = value.GetIfDict();
|
||||
if (!order) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string* const location = order->FindString(kSkuOrderLocationKey);
|
||||
if (!location || location->empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
orders.Set(*location, ParseSkuOrder(*order));
|
||||
}
|
||||
|
||||
return orders;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AdsServiceDelegate::AdsServiceDelegate(
|
||||
@@ -161,49 +52,6 @@ AdsServiceDelegate::AdsServiceDelegate(
|
||||
|
||||
AdsServiceDelegate::~AdsServiceDelegate() {}
|
||||
|
||||
std::string AdsServiceDelegate::GetDefaultSearchEngineName() {
|
||||
auto* prepopulate_data_resolver =
|
||||
TemplateURLPrepopulateData::ResolverFactory::GetForProfile(&*profile_);
|
||||
const auto template_url_data = prepopulate_data_resolver->GetFallbackSearch();
|
||||
const std::u16string& default_search_engine_name =
|
||||
template_url_data ? template_url_data->short_name() : u"";
|
||||
return base::UTF16ToUTF8(default_search_engine_name);
|
||||
}
|
||||
|
||||
base::Value::Dict AdsServiceDelegate::GetSkus() const {
|
||||
base::Value::Dict skus;
|
||||
|
||||
if (!local_state_->FindPreference(skus::prefs::kSkusState)) {
|
||||
// No SKUs in local state.
|
||||
return skus;
|
||||
}
|
||||
|
||||
const base::Value::Dict& skus_state =
|
||||
local_state_->GetDict(skus::prefs::kSkusState);
|
||||
for (const auto [environment, value] : skus_state) {
|
||||
if (!environment.starts_with(kSkuEnvironmentPrefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Deserialize the SKUs data from a JSON string stored in local state into a
|
||||
// dictionary object for further processing.
|
||||
std::optional<base::Value::Dict> sku_state =
|
||||
base::JSONReader::ReadDict(value.GetString());
|
||||
if (!sku_state) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const base::Value::Dict* const orders = sku_state->FindDict(kSkuOrdersKey);
|
||||
if (!orders) {
|
||||
continue;
|
||||
}
|
||||
|
||||
skus.Set(StripSkuEnvironmentPrefix(environment), ParseSkuOrders(*orders));
|
||||
}
|
||||
|
||||
return skus;
|
||||
}
|
||||
|
||||
void AdsServiceDelegate::OpenNewTabWithUrl(const GURL& url) {
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
// ServiceTabLauncher can currently only launch new tabs
|
||||
@@ -327,30 +175,6 @@ bool AdsServiceDelegate::IsFullScreenMode() {
|
||||
#endif
|
||||
}
|
||||
|
||||
base::Value::Dict AdsServiceDelegate::GetVirtualPrefs() {
|
||||
return base::Value::Dict()
|
||||
.Set("[virtual]:browser",
|
||||
base::Value::Dict()
|
||||
.Set("build_channel",
|
||||
version_info::GetChannelString(chrome::GetChannel()))
|
||||
.Set("version", version_info::GetVersionNumber())
|
||||
.Set("major_version", GetMajorVersion())
|
||||
.Set("minor_version", GetMinorVersion())
|
||||
.Set("build_version", GetBuildVersion())
|
||||
.Set("patch_version", GetPatchVersion()))
|
||||
.Set("[virtual]:operating_system",
|
||||
base::Value::Dict()
|
||||
.Set("locale", base::Value::Dict()
|
||||
.Set("language", CurrentLanguageCode())
|
||||
.Set("region", CurrentCountryCode()))
|
||||
.Set("is_mobile_platform", IsMobilePlatform())
|
||||
.Set("name", version_info::GetOSType()))
|
||||
.Set(
|
||||
"[virtual]:search_engine",
|
||||
base::Value::Dict().Set("default_name", GetDefaultSearchEngineName()))
|
||||
.Set("[virtual]:skus", GetSkus());
|
||||
}
|
||||
|
||||
NotificationDisplayService*
|
||||
AdsServiceDelegate::GetNotificationDisplayService() {
|
||||
return NotificationDisplayServiceFactory::GetForProfile(&*profile_);
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "base/values.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/ads_service.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
|
||||
@@ -42,10 +41,6 @@ class AdsServiceDelegate : public AdsService::Delegate {
|
||||
|
||||
~AdsServiceDelegate() override;
|
||||
|
||||
std::string GetDefaultSearchEngineName();
|
||||
|
||||
base::Value::Dict GetSkus() const;
|
||||
|
||||
// AdsService::Delegate:
|
||||
void MaybeInitNotificationHelper(base::OnceClosure callback) override;
|
||||
bool CanShowSystemNotificationsWhileBrowserIsBackgrounded() override;
|
||||
@@ -64,8 +59,6 @@ class AdsServiceDelegate : public AdsService::Delegate {
|
||||
void OpenNewTabWithUrl(const GURL& url) override;
|
||||
bool IsFullScreenMode() override;
|
||||
|
||||
base::Value::Dict GetVirtualPrefs() override;
|
||||
|
||||
private:
|
||||
NotificationDisplayService* GetNotificationDisplayService();
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "brave/browser/brave_ads/device_id/device_id_impl.h"
|
||||
#include "brave/browser/brave_ads/services/bat_ads_service_factory_impl.h"
|
||||
#include "brave/browser/brave_ads/tooltips/ads_tooltips_delegate_impl.h"
|
||||
#include "brave/browser/brave_ads/virtual_pref_provider_delegate.h"
|
||||
#include "brave/browser/brave_browser_process.h"
|
||||
#include "brave/browser/brave_rewards/rewards_service_factory.h"
|
||||
#include "brave/browser/brave_rewards/rewards_util.h"
|
||||
@@ -98,6 +99,7 @@ AdsServiceFactory::BuildServiceInstanceForBrowserContext(
|
||||
return std::make_unique<AdsServiceImpl>(
|
||||
std::move(delegate), profile->GetPrefs(),
|
||||
g_browser_process->local_state(),
|
||||
std::make_unique<VirtualPrefProviderDelegate>(*profile),
|
||||
profile->GetDefaultStoragePartition()
|
||||
->GetURLLoaderFactoryForBrowserProcess(),
|
||||
brave::GetChannelName(), profile->GetPath(), CreateAdsTooltipsDelegate(),
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/* 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/browser/brave_ads/virtual_pref_provider_delegate.h"
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/version_info/channel.h"
|
||||
#include "base/version_info/version_info.h"
|
||||
#include "chrome/browser/search_engines/template_url_prepopulate_data_resolver_factory.h"
|
||||
#include "chrome/common/channel_info.h"
|
||||
#include "components/search_engines/template_url_data.h"
|
||||
#include "components/search_engines/template_url_prepopulate_data.h"
|
||||
#include "components/search_engines/template_url_prepopulate_data_resolver.h"
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
VirtualPrefProviderDelegate::VirtualPrefProviderDelegate(Profile& profile)
|
||||
: profile_(profile) {}
|
||||
|
||||
VirtualPrefProviderDelegate::~VirtualPrefProviderDelegate() = default;
|
||||
|
||||
std::string VirtualPrefProviderDelegate::GetChannel() const {
|
||||
return std::string(version_info::GetChannelString(chrome::GetChannel()));
|
||||
}
|
||||
|
||||
std::string VirtualPrefProviderDelegate::GetDefaultSearchEngineName() const {
|
||||
auto* prepopulate_data_resolver =
|
||||
TemplateURLPrepopulateData::ResolverFactory::GetForProfile(&*profile_);
|
||||
const auto template_url_data = prepopulate_data_resolver->GetFallbackSearch();
|
||||
const std::u16string& default_search_engine_name =
|
||||
template_url_data ? template_url_data->short_name() : u"";
|
||||
return base::UTF16ToUTF8(default_search_engine_name);
|
||||
}
|
||||
|
||||
} // namespace brave_ads
|
||||
@@ -0,0 +1,38 @@
|
||||
/* 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_BROWSER_BRAVE_ADS_VIRTUAL_PREF_PROVIDER_DELEGATE_H_
|
||||
#define BRAVE_BROWSER_BRAVE_ADS_VIRTUAL_PREF_PROVIDER_DELEGATE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/virtual_pref_provider.h"
|
||||
|
||||
class Profile;
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
class VirtualPrefProviderDelegate : public VirtualPrefProvider::Delegate {
|
||||
public:
|
||||
explicit VirtualPrefProviderDelegate(Profile& profile);
|
||||
|
||||
VirtualPrefProviderDelegate(const VirtualPrefProviderDelegate&) = delete;
|
||||
VirtualPrefProviderDelegate& operator=(const VirtualPrefProviderDelegate&) =
|
||||
delete;
|
||||
|
||||
~VirtualPrefProviderDelegate() override;
|
||||
|
||||
std::string GetChannel() const override;
|
||||
|
||||
std::string GetDefaultSearchEngineName() const override;
|
||||
|
||||
private:
|
||||
const raw_ref<Profile> profile_;
|
||||
};
|
||||
|
||||
} // namespace brave_ads
|
||||
|
||||
#endif // BRAVE_BROWSER_BRAVE_ADS_VIRTUAL_PREF_PROVIDER_DELEGATE_H_
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "ios/chrome/browser/safe_browsing/model/safe_browsing_metrics_collector_factory.h"
|
||||
#include "ios/chrome/browser/saved_tab_groups/model/tab_group_service_factory.h"
|
||||
#include "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h"
|
||||
#include "ios/chrome/browser/search_engines/model/template_url_prepopulate_data_resolver_factory.h"
|
||||
#include "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
|
||||
#include "ios/chrome/browser/segmentation_platform/model/segmentation_platform_service_factory.h"
|
||||
#include "ios/chrome/browser/sessions/model/session_restoration_service_factory.h"
|
||||
@@ -100,6 +101,7 @@ void EnsureProfileKeyedServiceFactoriesBuilt() {
|
||||
ios::HostContentSettingsMapFactory::GetInstance();
|
||||
ios::LocalOrSyncableBookmarkSyncServiceFactory::GetInstance();
|
||||
ios::PasswordManagerLogRouterFactory::GetInstance();
|
||||
ios::TemplateURLPrepopulateDataResolverFactory::GetInstance();
|
||||
ios::TemplateURLServiceFactory::GetInstance();
|
||||
ios::TopSitesFactory::GetInstance();
|
||||
ios::WebDataServiceFactory::GetInstance();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "brave/components/brave_ads/browser/ads_service_impl.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
@@ -39,6 +40,7 @@
|
||||
#include "brave/components/brave_ads/browser/tooltips/ads_tooltips_delegate.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/ads_service_observer.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/new_tab_page_ad_prefetcher.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/virtual_pref_provider.h"
|
||||
#include "brave/components/brave_ads/core/public/ad_units/inline_content_ad/inline_content_ad_value_util.h"
|
||||
#include "brave/components/brave_ads/core/public/ad_units/new_tab_page_ad/new_tab_page_ad_value_util.h"
|
||||
#include "brave/components/brave_ads/core/public/ad_units/notification_ad/notification_ad_feature.h"
|
||||
@@ -179,6 +181,8 @@ AdsServiceImpl::AdsServiceImpl(
|
||||
std::unique_ptr<Delegate> delegate,
|
||||
PrefService* prefs,
|
||||
PrefService* local_state,
|
||||
std::unique_ptr<VirtualPrefProvider::Delegate>
|
||||
virtual_pref_provider_delegate,
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader,
|
||||
std::string_view channel_name,
|
||||
const base::FilePath& profile_path,
|
||||
@@ -192,6 +196,9 @@ AdsServiceImpl::AdsServiceImpl(
|
||||
: AdsService(std::move(delegate)),
|
||||
prefs_(prefs),
|
||||
local_state_(local_state),
|
||||
virtual_pref_provider_(std::make_unique<VirtualPrefProvider>(
|
||||
local_state_,
|
||||
std::move(virtual_pref_provider_delegate))),
|
||||
url_loader_(std::move(url_loader)),
|
||||
channel_name_(channel_name),
|
||||
history_service_(history_service),
|
||||
@@ -1883,7 +1890,7 @@ void AdsServiceImpl::HasLocalStatePrefPath(
|
||||
}
|
||||
|
||||
void AdsServiceImpl::GetVirtualPrefs(GetVirtualPrefsCallback callback) {
|
||||
std::move(callback).Run(delegate_->GetVirtualPrefs());
|
||||
std::move(callback).Run(virtual_pref_provider_->GetPrefs());
|
||||
}
|
||||
|
||||
void AdsServiceImpl::Log(const std::string& file,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "brave/components/brave_ads/browser/application_state/background_helper.h"
|
||||
#include "brave/components/brave_ads/browser/component_updater/resource_component_observer.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/ads_service.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/virtual_pref_provider.h"
|
||||
#include "brave/components/brave_ads/core/mojom/brave_ads.mojom.h"
|
||||
#include "brave/components/brave_ads/core/public/ads_callback.h"
|
||||
#include "brave/components/brave_ads/core/public/service/ads_service_callback.h"
|
||||
@@ -68,7 +69,6 @@ class DeviceId;
|
||||
class ResourceComponent;
|
||||
struct NewTabPageAdInfo;
|
||||
class NewTabPageAdPrefetcher;
|
||||
|
||||
class AdsServiceImpl final : public AdsService,
|
||||
public bat_ads::mojom::BatAdsClient,
|
||||
public bat_ads::mojom::BatAdsObserver,
|
||||
@@ -81,6 +81,8 @@ class AdsServiceImpl final : public AdsService,
|
||||
std::unique_ptr<Delegate> delegate,
|
||||
PrefService* prefs,
|
||||
PrefService* local_state,
|
||||
std::unique_ptr<VirtualPrefProvider::Delegate>
|
||||
virtual_pref_provider_delegate,
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader,
|
||||
std::string_view channel_name,
|
||||
const base::FilePath& profile_path,
|
||||
@@ -465,6 +467,8 @@ class AdsServiceImpl final : public AdsService,
|
||||
|
||||
const raw_ptr<PrefService> local_state_ = nullptr; // Not owned.
|
||||
|
||||
const std::unique_ptr<VirtualPrefProvider> virtual_pref_provider_;
|
||||
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_ = nullptr;
|
||||
|
||||
const std::string channel_name_;
|
||||
|
||||
@@ -10,6 +10,10 @@ source_set("service") {
|
||||
"ads_service_observer.h",
|
||||
"new_tab_page_ad_prefetcher.cc",
|
||||
"new_tab_page_ad_prefetcher.h",
|
||||
"virtual_pref_provider.cc",
|
||||
"virtual_pref_provider.h",
|
||||
"virtual_pref_provider_util.cc",
|
||||
"virtual_pref_provider_util.h",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
@@ -18,20 +22,35 @@ source_set("service") {
|
||||
"//brave/components/brave_ads/core/public:headers",
|
||||
"//brave/components/services/bat_ads/public/interfaces",
|
||||
"//components/keyed_service/core",
|
||||
"//components/prefs",
|
||||
"//mojo/public/cpp/bindings",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base/version_info",
|
||||
"//brave/components/skus/browser",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("unit_tests") {
|
||||
testonly = true
|
||||
|
||||
sources = [ "new_tab_page_ad_prefetcher_unittest.cc" ]
|
||||
sources = [
|
||||
"new_tab_page_ad_prefetcher_unittest.cc",
|
||||
"virtual_pref_provider_unittest.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":service",
|
||||
":test_support",
|
||||
"//base",
|
||||
"//base/test:test_support",
|
||||
"//base/version_info",
|
||||
"//brave/components/brave_ads/core",
|
||||
"//brave/components/brave_ads/core/public:test_support",
|
||||
"//brave/components/skus/browser",
|
||||
"//components/prefs:test_support",
|
||||
"//testing/gmock",
|
||||
"//testing/gtest",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ class AdsService : public KeyedService {
|
||||
virtual void CloseNotificationAd(const std::string& id, bool is_custom) = 0;
|
||||
virtual void OpenNewTabWithUrl(const GURL& url) = 0;
|
||||
virtual bool IsFullScreenMode() = 0;
|
||||
|
||||
virtual base::Value::Dict GetVirtualPrefs() = 0;
|
||||
};
|
||||
|
||||
explicit AdsService(std::unique_ptr<Delegate> delegate);
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/* 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_ads/core/browser/service/virtual_pref_provider.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/version_info/version_info.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/virtual_pref_provider_util.h"
|
||||
#include "brave/components/brave_ads/core/public/common/locale/locale_util.h"
|
||||
#include "brave/components/skus/browser/pref_names.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kSkuEnvironmentPrefix[] = "skus:";
|
||||
constexpr char kSkuOrdersKey[] = "orders";
|
||||
constexpr char kSkuOrderLocationKey[] = "location";
|
||||
constexpr char kSkuOrderCreatedAtKey[] = "created_at";
|
||||
constexpr char kSkuOrderExpiresAtKey[] = "expires_at";
|
||||
constexpr char kSkuOrderLastPaidAtKey[] = "last_paid_at";
|
||||
constexpr char kSkuOrderStatusKey[] = "status";
|
||||
|
||||
std::string StripSkuEnvironmentPrefix(const std::string& environment) {
|
||||
const size_t pos = environment.find(':');
|
||||
return environment.substr(pos + 1);
|
||||
}
|
||||
|
||||
std::string NormalizeSkuStatus(const std::string& status) {
|
||||
// Normalize the status field to use consistent (US) spelling, as the JSON
|
||||
// source localizes it (e.g., "cancelled" vs "canceled").
|
||||
return status == "cancelled" ? "canceled" : status;
|
||||
}
|
||||
|
||||
base::Value::Dict ParseSkuOrder(const base::Value::Dict& dict) {
|
||||
base::Value::Dict order;
|
||||
|
||||
if (const std::string* const created_at =
|
||||
dict.FindString(kSkuOrderCreatedAtKey)) {
|
||||
order.Set(kSkuOrderCreatedAtKey, *created_at);
|
||||
}
|
||||
|
||||
if (const std::string* const expires_at =
|
||||
dict.FindString(kSkuOrderExpiresAtKey)) {
|
||||
order.Set(kSkuOrderExpiresAtKey, *expires_at);
|
||||
}
|
||||
|
||||
if (const std::string* const last_paid_at =
|
||||
dict.FindString(kSkuOrderLastPaidAtKey)) {
|
||||
order.Set(kSkuOrderLastPaidAtKey, *last_paid_at);
|
||||
}
|
||||
|
||||
if (const std::string* const status = dict.FindString(kSkuOrderStatusKey)) {
|
||||
const std::string normalized_status = NormalizeSkuStatus(*status);
|
||||
order.Set(kSkuOrderStatusKey, normalized_status);
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
base::Value::Dict ParseSkuOrders(const base::Value::Dict& dict) {
|
||||
base::Value::Dict orders;
|
||||
|
||||
for (const auto [/*id*/ _, value] : dict) {
|
||||
const base::Value::Dict* const order = value.GetIfDict();
|
||||
if (!order) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string* const location = order->FindString(kSkuOrderLocationKey);
|
||||
if (!location || location->empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
orders.Set(*location, ParseSkuOrder(*order));
|
||||
}
|
||||
|
||||
return orders;
|
||||
}
|
||||
|
||||
base::Value::Dict GetSkus(PrefService* local_state) {
|
||||
base::Value::Dict skus;
|
||||
|
||||
if (!local_state->FindPreference(skus::prefs::kSkusState)) {
|
||||
// No SKUs in local state.
|
||||
return skus;
|
||||
}
|
||||
|
||||
const base::Value::Dict& skus_state =
|
||||
local_state->GetDict(skus::prefs::kSkusState);
|
||||
for (const auto [environment, value] : skus_state) {
|
||||
if (!environment.starts_with(kSkuEnvironmentPrefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Deserialize the SKUs data from a JSON string stored in local state into a
|
||||
// dictionary object for further processing.
|
||||
std::optional<base::Value::Dict> sku_state =
|
||||
base::JSONReader::ReadDict(value.GetString());
|
||||
if (!sku_state) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const base::Value::Dict* const orders = sku_state->FindDict(kSkuOrdersKey);
|
||||
if (!orders) {
|
||||
continue;
|
||||
}
|
||||
|
||||
skus.Set(StripSkuEnvironmentPrefix(environment), ParseSkuOrders(*orders));
|
||||
}
|
||||
|
||||
return skus;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
VirtualPrefProvider::VirtualPrefProvider(PrefService* local_state,
|
||||
std::unique_ptr<Delegate> delegate)
|
||||
: local_state_(local_state), delegate_(std::move(delegate)) {
|
||||
CHECK(local_state_);
|
||||
CHECK(delegate_);
|
||||
}
|
||||
|
||||
VirtualPrefProvider::~VirtualPrefProvider() = default;
|
||||
|
||||
base::Value::Dict VirtualPrefProvider::GetPrefs() {
|
||||
return base::Value::Dict()
|
||||
.Set("[virtual]:browser",
|
||||
base::Value::Dict()
|
||||
.Set("build_channel", delegate_->GetChannel())
|
||||
.Set("version", version_info::GetVersionNumber())
|
||||
.Set("major_version", GetMajorVersion())
|
||||
.Set("minor_version", GetMinorVersion())
|
||||
.Set("build_version", GetBuildVersion())
|
||||
.Set("patch_version", GetPatchVersion()))
|
||||
.Set("[virtual]:operating_system",
|
||||
base::Value::Dict()
|
||||
.Set("locale", base::Value::Dict()
|
||||
.Set("language", CurrentLanguageCode())
|
||||
.Set("region", CurrentCountryCode()))
|
||||
.Set("is_mobile_platform", IsMobilePlatform())
|
||||
.Set("name", version_info::GetOSType()))
|
||||
.Set("[virtual]:search_engine",
|
||||
base::Value::Dict().Set("default_name",
|
||||
delegate_->GetDefaultSearchEngineName()))
|
||||
.Set("[virtual]:skus", GetSkus(local_state_));
|
||||
}
|
||||
|
||||
} // namespace brave_ads
|
||||
@@ -0,0 +1,47 @@
|
||||
/* 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_ADS_CORE_BROWSER_SERVICE_VIRTUAL_PREF_PROVIDER_H_
|
||||
#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SERVICE_VIRTUAL_PREF_PROVIDER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/values.h"
|
||||
|
||||
class PrefService;
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
class VirtualPrefProvider final {
|
||||
public:
|
||||
class Delegate {
|
||||
public:
|
||||
virtual ~Delegate() = default;
|
||||
|
||||
virtual std::string GetChannel() const = 0;
|
||||
|
||||
virtual std::string GetDefaultSearchEngineName() const = 0;
|
||||
};
|
||||
|
||||
VirtualPrefProvider(PrefService* local_state,
|
||||
std::unique_ptr<Delegate> delegate);
|
||||
|
||||
VirtualPrefProvider(const VirtualPrefProvider&) = delete;
|
||||
VirtualPrefProvider& operator=(const VirtualPrefProvider&) = delete;
|
||||
|
||||
~VirtualPrefProvider();
|
||||
|
||||
base::Value::Dict GetPrefs();
|
||||
|
||||
private:
|
||||
const raw_ptr<PrefService> local_state_ = nullptr; // Not owned.
|
||||
const std::unique_ptr<Delegate> delegate_;
|
||||
};
|
||||
|
||||
} // namespace brave_ads
|
||||
|
||||
#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SERVICE_VIRTUAL_PREF_PROVIDER_H_
|
||||
@@ -0,0 +1,229 @@
|
||||
/* 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_ads/core/browser/service/virtual_pref_provider.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/test/values_test_util.h"
|
||||
#include "base/values.h"
|
||||
#include "base/version_info/version_info.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/virtual_pref_provider_util.h"
|
||||
#include "brave/components/brave_ads/core/public/common/locale/scoped_locale_for_testing.h"
|
||||
#include "brave/components/skus/browser/pref_names.h"
|
||||
#include "components/prefs/pref_registry_simple.h"
|
||||
#include "components/prefs/testing_pref_service.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BraveAds*
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
class VirtualPrefProviderDelegateMock : public VirtualPrefProvider::Delegate {
|
||||
public:
|
||||
MOCK_METHOD(std::string, GetChannel, (), (const));
|
||||
|
||||
MOCK_METHOD(std::string, GetDefaultSearchEngineName, (), (const));
|
||||
};
|
||||
|
||||
class VirtualPrefProviderTest : public ::testing::Test {
|
||||
public:
|
||||
VirtualPrefProviderTest() {
|
||||
auto delegate = std::make_unique<VirtualPrefProviderDelegateMock>();
|
||||
delegate_ = delegate.get();
|
||||
provider_ = std::make_unique<VirtualPrefProvider>(&pref_service_,
|
||||
std::move(delegate));
|
||||
|
||||
pref_service_.registry()->RegisterDictionaryPref(skus::prefs::kSkusState);
|
||||
}
|
||||
|
||||
~VirtualPrefProviderTest() override {
|
||||
// Reset delegate to avoid dangling pointer.
|
||||
delegate_ = nullptr;
|
||||
}
|
||||
|
||||
TestingPrefServiceSimple& pref_service() { return pref_service_; }
|
||||
|
||||
VirtualPrefProviderDelegateMock& delegate() const { return *delegate_; }
|
||||
|
||||
VirtualPrefProvider& provider() const { return *provider_; }
|
||||
|
||||
private:
|
||||
TestingPrefServiceSimple pref_service_;
|
||||
raw_ptr<VirtualPrefProviderDelegateMock> delegate_ = nullptr;
|
||||
std::unique_ptr<VirtualPrefProvider> provider_;
|
||||
};
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, BrowserBuildChannel) {
|
||||
// Arrange
|
||||
EXPECT_CALL(delegate(), GetChannel).WillOnce(testing::Return("release"));
|
||||
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
const std::string* build_channel =
|
||||
virtual_prefs.FindStringByDottedPath("[virtual]:browser.build_channel");
|
||||
ASSERT_TRUE(build_channel);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(*build_channel, "release");
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, BrowserVersion) {
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
const std::string* version =
|
||||
virtual_prefs.FindStringByDottedPath("[virtual]:browser.version");
|
||||
ASSERT_TRUE(version);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(*version, version_info::GetVersionNumber());
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, BrowserMajorVersion) {
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
std::optional<int> major_version =
|
||||
virtual_prefs.FindIntByDottedPath("[virtual]:browser.major_version");
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(major_version, GetMajorVersion());
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, BrowserMinorVersion) {
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
std::optional<int> minor_version =
|
||||
virtual_prefs.FindIntByDottedPath("[virtual]:browser.minor_version");
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(minor_version, GetMinorVersion());
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, BrowserBuildVersion) {
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
std::optional<int> build_version =
|
||||
virtual_prefs.FindIntByDottedPath("[virtual]:browser.build_version");
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(build_version, GetBuildVersion());
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, BrowserPatchVersion) {
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
std::optional<int> patch_version =
|
||||
virtual_prefs.FindIntByDottedPath("[virtual]:browser.patch_version");
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(patch_version, GetPatchVersion());
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, OperatingSystemLocaleLanguage) {
|
||||
// Arrange
|
||||
const test::ScopedCurrentLanguageCode scoped_current_language_code{"en"};
|
||||
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
const std::string* language = virtual_prefs.FindStringByDottedPath(
|
||||
"[virtual]:operating_system.locale.language");
|
||||
ASSERT_TRUE(language);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(*language, "en");
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, OperatingSystemLocaleRegion) {
|
||||
// Arrange
|
||||
const test::ScopedCurrentCountryCode scoped_current_country_code{"KY"};
|
||||
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
const std::string* region = virtual_prefs.FindStringByDottedPath(
|
||||
"[virtual]:operating_system.locale.region");
|
||||
ASSERT_TRUE(region);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(*region, "KY");
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, OperatingSystemIsMobilePlatform) {
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
std::optional<bool> is_mobile_platform = virtual_prefs.FindBoolByDottedPath(
|
||||
"[virtual]:operating_system.is_mobile_platform");
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(is_mobile_platform, IsMobilePlatform());
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, OperatingSystemName) {
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
const std::string* name =
|
||||
virtual_prefs.FindStringByDottedPath("[virtual]:operating_system.name");
|
||||
ASSERT_TRUE(name);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(*name, version_info::GetOSType());
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, SearchEngineDefaultName) {
|
||||
// Arrange
|
||||
EXPECT_CALL(delegate(), GetDefaultSearchEngineName)
|
||||
.WillOnce(testing::Return("Brave"));
|
||||
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
const std::string* default_search_engine_name =
|
||||
virtual_prefs.FindStringByDottedPath(
|
||||
"[virtual]:search_engine.default_name");
|
||||
ASSERT_TRUE(default_search_engine_name);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(*default_search_engine_name, "Brave");
|
||||
}
|
||||
|
||||
TEST_F(VirtualPrefProviderTest, PrefsWithSkus) {
|
||||
// Arrange
|
||||
pref_service().SetDict(skus::prefs::kSkusState,
|
||||
base::Value::Dict().Set("skus:development", R"JSON({
|
||||
"orders": {
|
||||
"f24787ab-7bc3-46b9-bc05-65befb360cb8": {
|
||||
"created_at": "2023-10-24T16:00:57.902289",
|
||||
"expires_at": "2023-12-24T17:03:59.030987",
|
||||
"last_paid_at": "2023-11-24T17:03:59.030987",
|
||||
"location": "leo.brave.com",
|
||||
"status": "paid"
|
||||
}
|
||||
}
|
||||
})JSON"));
|
||||
|
||||
// Act
|
||||
const base::Value::Dict virtual_prefs = provider().GetPrefs();
|
||||
const base::Value::Dict* skus = virtual_prefs.FindDict("[virtual]:skus");
|
||||
ASSERT_TRUE(skus);
|
||||
|
||||
// Assert
|
||||
const base::Value::Dict expected_skus = base::test::ParseJsonDict(
|
||||
R"JSON(
|
||||
{
|
||||
"development": {
|
||||
"leo.brave.com": {
|
||||
"created_at": "2023-10-24T16:00:57.902289",
|
||||
"expires_at": "2023-12-24T17:03:59.030987",
|
||||
"last_paid_at": "2023-11-24T17:03:59.030987",
|
||||
"status": "paid"
|
||||
}
|
||||
}
|
||||
})JSON");
|
||||
EXPECT_EQ(expected_skus, *skus);
|
||||
}
|
||||
|
||||
} // namespace brave_ads
|
||||
@@ -0,0 +1,50 @@
|
||||
/* 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_ads/core/browser/service/virtual_pref_provider_util.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "base/version.h"
|
||||
#include "base/version_info/version_info.h"
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
namespace {
|
||||
|
||||
int GetVersionComponent(size_t index) {
|
||||
const base::Version& version = version_info::GetVersion();
|
||||
const std::vector<uint32_t>& version_components = version.components();
|
||||
return index < version_components.size()
|
||||
? static_cast<int>(version_components[index])
|
||||
: 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int GetMajorVersion() {
|
||||
return GetVersionComponent(0);
|
||||
}
|
||||
|
||||
int GetMinorVersion() {
|
||||
return GetVersionComponent(1);
|
||||
}
|
||||
|
||||
int GetBuildVersion() {
|
||||
return GetVersionComponent(2);
|
||||
}
|
||||
|
||||
int GetPatchVersion() {
|
||||
return GetVersionComponent(3);
|
||||
}
|
||||
|
||||
bool IsMobilePlatform() {
|
||||
std::string_view operating_system_name = version_info::GetOSType();
|
||||
return operating_system_name == "Android" || operating_system_name == "iOS";
|
||||
}
|
||||
|
||||
} // namespace brave_ads
|
||||
@@ -0,0 +1,23 @@
|
||||
/* 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_ADS_CORE_BROWSER_SERVICE_VIRTUAL_PREF_PROVIDER_UTIL_H_
|
||||
#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SERVICE_VIRTUAL_PREF_PROVIDER_UTIL_H_
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
int GetMajorVersion();
|
||||
|
||||
int GetMinorVersion();
|
||||
|
||||
int GetBuildVersion();
|
||||
|
||||
int GetPatchVersion();
|
||||
|
||||
bool IsMobilePlatform();
|
||||
|
||||
} // namespace brave_ads
|
||||
|
||||
#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SERVICE_VIRTUAL_PREF_PROVIDER_UTIL_H_
|
||||
@@ -57,3 +57,9 @@ source_set("headers") {
|
||||
|
||||
public_deps = [ "//brave/components/brave_ads/core/mojom" ]
|
||||
}
|
||||
|
||||
source_set("test_support") {
|
||||
testonly = true
|
||||
|
||||
sources = [ "common/locale/scoped_locale_for_testing.h" ]
|
||||
}
|
||||
|
||||
@@ -660,7 +660,6 @@ source_set("brave_ads_unit_tests") {
|
||||
"//brave/components/brave_ads/core/internal/user_engagement/site_visit/site_visit_observer_mock.h",
|
||||
"//brave/components/brave_ads/core/internal/user_engagement/site_visit/site_visit_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/user_engagement/site_visit/site_visit_util_unittest.cc",
|
||||
"//brave/components/brave_ads/core/public/common/locale/scoped_locale_for_testing.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@@ -668,6 +667,7 @@ source_set("brave_ads_unit_tests") {
|
||||
"//brave/components/brave_ads/core",
|
||||
"//brave/components/brave_ads/core/browser/service:unit_tests",
|
||||
"//brave/components/brave_ads/core/internal",
|
||||
"//brave/components/brave_ads/core/public:test_support",
|
||||
"//brave/components/brave_news/common",
|
||||
"//brave/components/brave_rewards/core",
|
||||
"//brave/components/challenge_bypass_ristretto",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include_rules = [
|
||||
"+brave/components/brave_ads/core/browser",
|
||||
"+brave/components/brave_ads/core/mojom",
|
||||
"+brave/components/brave_ads/core/public",
|
||||
"+brave/components/brave_news/common",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "base/types/optional_ref.h"
|
||||
#include "base/values.h"
|
||||
#import "brave/build/ios/mojom/cpp_transformations.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/virtual_pref_provider.h"
|
||||
#include "brave/components/brave_ads/core/mojom/brave_ads.mojom.h"
|
||||
#include "brave/components/brave_ads/core/public/ad_units/inline_content_ad/inline_content_ad_info.h"
|
||||
#include "brave/components/brave_ads/core/public/ad_units/new_tab_page_ad/new_tab_page_ad_info.h"
|
||||
@@ -58,6 +59,7 @@
|
||||
#import "brave/ios/browser/api/common/common_operations.h"
|
||||
#include "brave/ios/browser/brave_ads/ads_service_factory_ios.h"
|
||||
#include "brave/ios/browser/brave_ads/ads_service_impl_ios.h"
|
||||
#include "brave/ios/browser/brave_ads/virtual_pref_provider_delegate_ios.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "ios/chrome/browser/shared/model/application_context/application_context.h"
|
||||
@@ -110,6 +112,7 @@ constexpr NSString* kAdsResourceComponentMetadataVersion = @".v1";
|
||||
|
||||
@interface BraveAds () <AdsClientBridge> {
|
||||
std::unique_ptr<brave_ads::AdsClientNotifier> adsClientNotifier;
|
||||
std::unique_ptr<brave_ads::VirtualPrefProvider> virtualPrefProvider;
|
||||
raw_ptr<brave_ads::AdsServiceImplIOS> adsService;
|
||||
nw_path_monitor_t networkMonitor;
|
||||
dispatch_queue_t monitorQueue;
|
||||
@@ -152,6 +155,12 @@ constexpr NSString* kAdsResourceComponentMetadataVersion = @".v1";
|
||||
[self initObservers];
|
||||
|
||||
adsClientNotifier = std::make_unique<brave_ads::AdsClientNotifier>();
|
||||
|
||||
ProfileIOS* profile = [self getLastUsedProfile];
|
||||
CHECK(profile);
|
||||
virtualPrefProvider = std::make_unique<brave_ads::VirtualPrefProvider>(
|
||||
self.localStatePrefService,
|
||||
std::make_unique<brave_ads::VirtualPrefProviderDelegateIOS>(*profile));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -163,6 +172,8 @@ constexpr NSString* kAdsResourceComponentMetadataVersion = @".v1";
|
||||
|
||||
[self stopNetworkMonitor];
|
||||
|
||||
virtualPrefProvider.reset();
|
||||
|
||||
[self deallocAdsClientNotifier];
|
||||
|
||||
[self cleanupAdsService];
|
||||
@@ -1435,7 +1446,11 @@ constexpr NSString* kAdsResourceComponentMetadataVersion = @".v1";
|
||||
}
|
||||
|
||||
- (base::Value::Dict)getVirtualPrefs {
|
||||
return {};
|
||||
if (virtualPrefProvider == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return virtualPrefProvider->GetPrefs();
|
||||
}
|
||||
|
||||
- (void)log:(const char*)file
|
||||
|
||||
@@ -9,13 +9,19 @@ source_set("brave_ads") {
|
||||
"ads_service_factory_ios.mm",
|
||||
"ads_service_impl_ios.h",
|
||||
"ads_service_impl_ios.mm",
|
||||
"virtual_pref_provider_delegate_ios.h",
|
||||
"virtual_pref_provider_delegate_ios.mm",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base/version_info",
|
||||
"//components/pref_registry",
|
||||
"//components/prefs",
|
||||
"//components/search_engines",
|
||||
"//ios/chrome/browser/search_engines/model",
|
||||
"//ios/chrome/browser/shared/model/profile",
|
||||
"//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
|
||||
"//ios/chrome/common",
|
||||
"//ios/web/public",
|
||||
"//sql",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* 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_IOS_BROWSER_BRAVE_ADS_VIRTUAL_PREF_PROVIDER_DELEGATE_IOS_H_
|
||||
#define BRAVE_IOS_BROWSER_BRAVE_ADS_VIRTUAL_PREF_PROVIDER_DELEGATE_IOS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "brave/components/brave_ads/core/browser/service/virtual_pref_provider.h"
|
||||
|
||||
class ProfileIOS;
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
class VirtualPrefProviderDelegateIOS : public VirtualPrefProvider::Delegate {
|
||||
public:
|
||||
explicit VirtualPrefProviderDelegateIOS(ProfileIOS& profile);
|
||||
|
||||
VirtualPrefProviderDelegateIOS(const VirtualPrefProviderDelegateIOS&) =
|
||||
delete;
|
||||
VirtualPrefProviderDelegateIOS& operator=(
|
||||
const VirtualPrefProviderDelegateIOS&) = delete;
|
||||
|
||||
~VirtualPrefProviderDelegateIOS() override;
|
||||
|
||||
std::string GetChannel() const override;
|
||||
|
||||
std::string GetDefaultSearchEngineName() const override;
|
||||
|
||||
private:
|
||||
const raw_ref<ProfileIOS> profile_;
|
||||
};
|
||||
|
||||
} // namespace brave_ads
|
||||
|
||||
#endif // BRAVE_IOS_BROWSER_BRAVE_ADS_VIRTUAL_PREF_PROVIDER_DELEGATE_IOS_H_
|
||||
@@ -0,0 +1,38 @@
|
||||
/* 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/ios/browser/brave_ads/virtual_pref_provider_delegate_ios.h"
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/version_info/channel.h"
|
||||
#include "components/search_engines/template_url_data.h"
|
||||
#include "components/search_engines/template_url_prepopulate_data.h"
|
||||
#include "components/search_engines/template_url_prepopulate_data_resolver.h"
|
||||
#include "ios/chrome/browser/search_engines/model/template_url_prepopulate_data_resolver_factory.h"
|
||||
#include "ios/chrome/browser/shared/model/profile/profile_ios.h"
|
||||
#include "ios/chrome/common/channel_info.h"
|
||||
|
||||
namespace brave_ads {
|
||||
|
||||
VirtualPrefProviderDelegateIOS::VirtualPrefProviderDelegateIOS(
|
||||
ProfileIOS& profile)
|
||||
: profile_(profile) {}
|
||||
|
||||
VirtualPrefProviderDelegateIOS::~VirtualPrefProviderDelegateIOS() = default;
|
||||
|
||||
std::string VirtualPrefProviderDelegateIOS::GetChannel() const {
|
||||
return std::string(version_info::GetChannelString(::GetChannel()));
|
||||
}
|
||||
|
||||
std::string VirtualPrefProviderDelegateIOS::GetDefaultSearchEngineName() const {
|
||||
auto* prepopulate_data_resolver =
|
||||
ios::TemplateURLPrepopulateDataResolverFactory::GetForProfile(&*profile_);
|
||||
const auto template_url_data = prepopulate_data_resolver->GetFallbackSearch();
|
||||
const std::u16string& default_search_engine_name =
|
||||
template_url_data ? template_url_data->short_name() : u"";
|
||||
return base::UTF16ToUTF8(default_search_engine_name);
|
||||
}
|
||||
|
||||
} // namespace brave_ads
|
||||
Reference in New Issue
Block a user