From 3647090bc8bf2798f221df17789400eaa3eec4d4 Mon Sep 17 00:00:00 2001 From: Aleksey Seren Date: Tue, 3 Sep 2024 19:37:45 -0500 Subject: [PATCH] [ads] Add search result ad clicked InfoBar on desktop & android --- .../infobar/BraveInfoBarIdentifier.java | 4 +- app/brave_generated_resources.grd | 3 + ...arch_result_ad_clicked_infobar_delegate.cc | 90 ++++++++++++++ ...earch_result_ad_clicked_infobar_delegate.h | 44 +++++++ .../creative_search_result_ad_tab_helper.cc | 34 +++++- .../creative_search_result_ad_tab_helper.h | 9 +- browser/brave_ads/sources.gni | 3 + .../infobars/core/infobar_delegate.h | 3 +- .../creative_search_result_ad_handler.cc | 6 +- .../creative_search_result_ad_handler.h | 4 +- ...ative_search_result_ad_handler_unittest.cc | 113 ++++++++++++++---- .../core/internal/prefs/pref_registry.cc | 3 + .../brave_ads/core/public/prefs/pref_names.h | 3 + 13 files changed, 281 insertions(+), 38 deletions(-) create mode 100644 browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.cc create mode 100644 browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.h diff --git a/android/java/org/chromium/chrome/browser/infobar/BraveInfoBarIdentifier.java b/android/java/org/chromium/chrome/browser/infobar/BraveInfoBarIdentifier.java index aae1d446b20f..5e8af25235a3 100644 --- a/android/java/org/chromium/chrome/browser/infobar/BraveInfoBarIdentifier.java +++ b/android/java/org/chromium/chrome/browser/infobar/BraveInfoBarIdentifier.java @@ -17,7 +17,8 @@ BraveInfoBarIdentifier.BRAVE_CONFIRM_P3A_INFOBAR_DELEGATE, BraveInfoBarIdentifier.SYNC_CANNOT_RUN_INFOBAR, BraveInfoBarIdentifier.WEB_DISCOVERY_INFOBAR_DELEGATE, - BraveInfoBarIdentifier.BRAVE_SYNC_ACCOUNT_DELETED_INFOBAR + BraveInfoBarIdentifier.BRAVE_SYNC_ACCOUNT_DELETED_INFOBAR, + BraveInfoBarIdentifier.SEARCH_RESULT_AD_CLICKED_INFOBAR_DELEGATE }) @Retention(RetentionPolicy.SOURCE) public @interface BraveInfoBarIdentifier { @@ -29,4 +30,5 @@ int SYNC_CANNOT_RUN_INFOBAR = 505; int WEB_DISCOVERY_INFOBAR_DELEGATE = 506; int BRAVE_SYNC_ACCOUNT_DELETED_INFOBAR = 507; + int SEARCH_RESULT_AD_CLICKED_INFOBAR_DELEGATE = 510; } diff --git a/app/brave_generated_resources.grd b/app/brave_generated_resources.grd index 3d5ae0891386..4d32610f6a88 100644 --- a/app/brave_generated_resources.grd +++ b/app/brave_generated_resources.grd @@ -655,6 +655,9 @@ Or change later at $2brave://settings/ext You don't need to click to earn, but do click if you're interested! + + You’ve just clicked on a Brave Search ad. Unlike Big Tech, we measure ad performance anonymously and preserve your privacy. + diff --git a/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.cc b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.cc new file mode 100644 index 000000000000..4b5c9188f6d0 --- /dev/null +++ b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.cc @@ -0,0 +1,90 @@ +/* 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/. */ + +#include "brave/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.h" + +#include + +#include "brave/components/brave_ads/core/public/prefs/pref_names.h" +#include "brave/components/vector_icons/vector_icons.h" +#include "brave/grit/brave_generated_resources.h" +#include "chrome/browser/infobars/confirm_infobar_creator.h" +#include "components/infobars/content/content_infobar_manager.h" +#include "components/infobars/core/infobar.h" +#include "components/prefs/pref_service.h" +#include "components/strings/grit/components_strings.h" +#include "components/vector_icons/vector_icons.h" +#include "content/public/browser/web_contents.h" +#include "ui/base/l10n/l10n_util.h" +#include "url/gurl.h" + +namespace brave_ads { + +namespace { + +constexpr char kLearnMoreUrl[] = + "https://support.brave.com/hc/en-us/articles/360026361072-Brave-Ads-FAQ"; + +} // namespace + +// static +void CreativeSearchResultAdClickedInfoBarDelegate::Create( + content::WebContents* web_contents, + PrefService* prefs) { + CHECK(web_contents); + CHECK(prefs); + + infobars::ContentInfoBarManager* infobar_manager = + infobars::ContentInfoBarManager::FromWebContents(web_contents); + if (!infobar_manager) { + return; + } + + if (!prefs->GetBoolean(prefs::kShouldShowSearchResultAdClickedInfoBar)) { + return; + } + prefs->SetBoolean(prefs::kShouldShowSearchResultAdClickedInfoBar, false); + + infobar_manager->AddInfoBar( + CreateConfirmInfoBar(std::unique_ptr( + new CreativeSearchResultAdClickedInfoBarDelegate()))); +} + +CreativeSearchResultAdClickedInfoBarDelegate:: + CreativeSearchResultAdClickedInfoBarDelegate() = default; + +CreativeSearchResultAdClickedInfoBarDelegate:: + ~CreativeSearchResultAdClickedInfoBarDelegate() = default; + +infobars::InfoBarDelegate::InfoBarIdentifier +CreativeSearchResultAdClickedInfoBarDelegate::GetIdentifier() const { + return SEARCH_RESULT_AD_CLICKED_INFOBAR_DELEGATE; +} + +const gfx::VectorIcon& +CreativeSearchResultAdClickedInfoBarDelegate::GetVectorIcon() const { + return kLeoBraveIconMonochromeIcon; +} + +std::u16string CreativeSearchResultAdClickedInfoBarDelegate::GetMessageText() + const { + return l10n_util::GetStringUTF16( + IDS_BRAVE_ADS_SEARCH_RESULT_AD_CLICKED_INFOBAR_MESSAGE); +} + +int CreativeSearchResultAdClickedInfoBarDelegate::GetButtons() const { + return BUTTON_NONE; +} + +std::u16string CreativeSearchResultAdClickedInfoBarDelegate::GetLinkText() + const { + return l10n_util::GetStringUTF16(IDS_LEARN_MORE); +} + +GURL CreativeSearchResultAdClickedInfoBarDelegate::GetLinkURL() const { + return GURL(kLearnMoreUrl); +} + +} // namespace brave_ads diff --git a/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.h b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.h new file mode 100644 index 000000000000..ccf02db1e427 --- /dev/null +++ b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.h @@ -0,0 +1,44 @@ +/* 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_BROWSER_BRAVE_ADS_CREATIVES_SEARCH_RESULT_AD_CREATIVE_SEARCH_RESULT_AD_CLICKED_INFOBAR_DELEGATE_H_ +#define BRAVE_BROWSER_BRAVE_ADS_CREATIVES_SEARCH_RESULT_AD_CREATIVE_SEARCH_RESULT_AD_CLICKED_INFOBAR_DELEGATE_H_ + +#include "components/infobars/core/confirm_infobar_delegate.h" + +class PrefService; + +namespace content { +class WebContents; +} // namespace content + +namespace brave_ads { + +class CreativeSearchResultAdClickedInfoBarDelegate + : public ConfirmInfoBarDelegate { + public: + CreativeSearchResultAdClickedInfoBarDelegate(); + ~CreativeSearchResultAdClickedInfoBarDelegate() override; + + CreativeSearchResultAdClickedInfoBarDelegate( + const CreativeSearchResultAdClickedInfoBarDelegate&) = delete; + CreativeSearchResultAdClickedInfoBarDelegate& operator=( + const CreativeSearchResultAdClickedInfoBarDelegate&) = delete; + + static void Create(content::WebContents* web_contents, PrefService* prefs); + + private: + // ConfirmInfoBarDelegate: + infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; + const gfx::VectorIcon& GetVectorIcon() const override; + std::u16string GetMessageText() const override; + int GetButtons() const override; + std::u16string GetLinkText() const override; + GURL GetLinkURL() const override; +}; + +} // namespace brave_ads + +#endif // BRAVE_BROWSER_BRAVE_ADS_CREATIVES_SEARCH_RESULT_AD_CREATIVE_SEARCH_RESULT_AD_CLICKED_INFOBAR_DELEGATE_H_ diff --git a/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.cc b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.cc index 086d83877151..5a38b001b133 100644 --- a/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.cc +++ b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.cc @@ -5,12 +5,15 @@ #include "brave/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.h" +#include + #include "base/check.h" #include "base/check_is_test.h" #include "base/functional/bind.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "brave/browser/brave_ads/ads_service_factory.h" +#include "brave/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.h" #include "brave/components/brave_ads/browser/ads_service.h" #include "brave/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.h" #include "brave/components/brave_ads/core/public/ads_feature.h" @@ -92,15 +95,15 @@ bool CreativeSearchResultAdTabHelper::ShouldHandleCreativeAdEvents() const { // If the feature is enabled, we should only trigger creative ad events when // the user has joined Brave Rewards. - const Profile* const profile = - Profile::FromBrowserContext(web_contents()->GetBrowserContext()); - return profile->GetPrefs()->GetBoolean(brave_rewards::prefs::kEnabled); + return GetPrefs()->GetBoolean(brave_rewards::prefs::kEnabled); } void CreativeSearchResultAdTabHelper::MaybeTriggerCreativeAdClickedEvent( - const GURL& url) { + const GURL& url, + base::OnceCallback callback) { if (creative_search_result_ad_handler_) { - creative_search_result_ad_handler_->MaybeTriggerCreativeAdClickedEvent(url); + creative_search_result_ad_handler_->MaybeTriggerCreativeAdClickedEvent( + url, std::move(callback)); } } @@ -118,6 +121,22 @@ AdsService* CreativeSearchResultAdTabHelper::GetAdsService() const { return AdsServiceFactory::GetForProfile(profile); } +PrefService* CreativeSearchResultAdTabHelper::GetPrefs() const { + Profile* const profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + return profile->GetPrefs(); +} + +void CreativeSearchResultAdTabHelper:: + MaybeTriggerCreativeAdClickedEventCallback(const bool success) { + if (!success) { + return; + } + + CreativeSearchResultAdClickedInfoBarDelegate::Create(web_contents(), + GetPrefs()); +} + void CreativeSearchResultAdTabHelper::MaybeCreateCreativeSearchResultAdHandler( content::NavigationHandle* const navigation_handle) { CHECK(navigation_handle); @@ -230,7 +249,10 @@ void CreativeSearchResultAdTabHelper::MaybeHandleCreativeAdClickedEvent( CHECK(!navigation_handle->GetRedirectChain().empty()); const GURL url = navigation_handle->GetRedirectChain().back(); - creative_search_result_ad_tab_helper->MaybeTriggerCreativeAdClickedEvent(url); + creative_search_result_ad_tab_helper->MaybeTriggerCreativeAdClickedEvent( + url, base::BindOnce(&CreativeSearchResultAdTabHelper:: + MaybeTriggerCreativeAdClickedEventCallback, + weak_factory_.GetWeakPtr())); } void CreativeSearchResultAdTabHelper::DidStartNavigation( diff --git a/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.h b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.h index dbd6dedb3e99..415536653a7b 100644 --- a/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.h +++ b/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.h @@ -15,6 +15,7 @@ #include "content/public/browser/web_contents_user_data.h" class GURL; +class PrefService; namespace brave_ads { @@ -39,13 +40,19 @@ class CreativeSearchResultAdTabHelper bool ShouldHandleCreativeAdEvents() const; - void MaybeTriggerCreativeAdClickedEvent(const GURL& url); + void MaybeTriggerCreativeAdClickedEvent( + const GURL& url, + base::OnceCallback callback); private: friend class content::WebContentsUserData; AdsService* GetAdsService() const; + PrefService* GetPrefs() const; + + void MaybeTriggerCreativeAdClickedEventCallback(bool success); + void MaybeCreateCreativeSearchResultAdHandler( content::NavigationHandle* navigation_handle); diff --git a/browser/brave_ads/sources.gni b/browser/brave_ads/sources.gni index a6f0de4792f3..5be05849b818 100644 --- a/browser/brave_ads/sources.gni +++ b/browser/brave_ads/sources.gni @@ -17,6 +17,8 @@ brave_browser_brave_ads_sources = [ "//brave/browser/brave_ads/application_state/notification_helper/notification_helper.h", "//brave/browser/brave_ads/application_state/notification_helper/notification_helper_impl.cc", "//brave/browser/brave_ads/application_state/notification_helper/notification_helper_impl.h", + "//brave/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.cc", + "//brave/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_clicked_infobar_delegate.h", "//brave/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.cc", "//brave/browser/brave_ads/creatives/search_result_ad/creative_search_result_ad_tab_helper.h", "//brave/browser/brave_ads/tabs/ads_tab_helper.cc", @@ -32,6 +34,7 @@ brave_browser_brave_ads_deps = [ "//brave/components/brave_ads/browser", "//brave/components/brave_ads/content/browser", "//brave/components/brave_ads/core", + "//brave/components/vector_icons", "//chrome/browser/notifications", "//chrome/browser/profiles", "//chrome/browser/profiles:profile", diff --git a/chromium_src/components/infobars/core/infobar_delegate.h b/chromium_src/components/infobars/core/infobar_delegate.h index 91848314bc83..8d829c8da85e 100644 --- a/chromium_src/components/infobars/core/infobar_delegate.h +++ b/chromium_src/components/infobars/core/infobar_delegate.h @@ -17,7 +17,8 @@ WEB_DISCOVERY_INFOBAR_DELEGATE = 506, \ BRAVE_SYNC_ACCOUNT_DELETED_INFOBAR = 507, \ BRAVE_REQUEST_OTR_INFOBAR_DELEGATE = 508, \ - DEV_CHANNEL_DEPRECATION_INFOBAR_DELEGATE = 509, + DEV_CHANNEL_DEPRECATION_INFOBAR_DELEGATE = 509, \ + SEARCH_RESULT_AD_CLICKED_INFOBAR_DELEGATE = 510, // Deprecated: // WAYBACK_MACHINE_INFOBAR_DELEGATE = 502 diff --git a/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.cc b/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.cc index 38ba6ef70bb7..bead2459fe42 100644 --- a/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.cc +++ b/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.cc @@ -77,7 +77,8 @@ void CreativeSearchResultAdHandler:: } void CreativeSearchResultAdHandler::MaybeTriggerCreativeAdClickedEvent( - const GURL& url) { + const GURL& url, + base::OnceCallback callback) { if (!creative_search_result_ads_) { // No creative search result ads are present on the web page. return; @@ -100,8 +101,7 @@ void CreativeSearchResultAdHandler::MaybeTriggerCreativeAdClickedEvent( ads_service_->TriggerSearchResultAdEvent( creative_search_result_ad->Clone(), - mojom::SearchResultAdEventType::kClicked, - /*intentional*/ base::DoNothing()); + mojom::SearchResultAdEventType::kClicked, std::move(callback)); } /////////////////////////////////////////////////////////////////////////////// diff --git a/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.h b/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.h index ef398375e487..5b44005224a7 100644 --- a/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.h +++ b/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler.h @@ -53,7 +53,9 @@ class CreativeSearchResultAdHandler final { ExtractCreativeAdPlacementIdsFromWebPageCallback callback); void MaybeTriggerCreativeAdViewedEvent(const std::string& placement_id); - void MaybeTriggerCreativeAdClickedEvent(const GURL& url); + void MaybeTriggerCreativeAdClickedEvent( + const GURL& url, + base::OnceCallback callback); private: friend class BraveAdsCreativeSearchResultAdHandlerTest; diff --git a/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler_unittest.cc b/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler_unittest.cc index 351ba721dcf2..d0254eb92a02 100644 --- a/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler_unittest.cc +++ b/components/brave_ads/content/browser/creatives/search_result_ad/creative_search_result_ad_handler_unittest.cc @@ -149,16 +149,24 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, ::testing::_)) .Times(0); - EXPECT_CALL(ads_service_mock_, - TriggerSearchResultAdEvent( - ::testing::_, mojom::SearchResultAdEventType::kClicked, - ::testing::_)); + EXPECT_CALL( + ads_service_mock_, + TriggerSearchResultAdEvent( + ::testing::_, mojom::SearchResultAdEventType::kClicked, ::testing::_)) + .WillOnce([](mojom::CreativeSearchResultAdInfoPtr, + mojom::SearchResultAdEventType, + TriggerAdEventCallback callback) { + std::move(callback).Run(/*success=*/false); + }); SimulateMaybeExtractCreativeAdPlacementIdsFromWebPageCallback( creative_search_result_ad_handler.get(), std::move(mojom_web_page)); + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/false)); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrl()); + ClickRedirectUrl(), callback.Get()); } TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, @@ -187,8 +195,11 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, SimulateMaybeExtractCreativeAdPlacementIdsFromWebPageCallback( creative_search_result_ad_handler.get(), blink::mojom::WebPagePtr()); + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/::testing::_)).Times(0); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrl()); + ClickRedirectUrl(), callback.Get()); } TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, @@ -217,8 +228,11 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, SimulateMaybeExtractCreativeAdPlacementIdsFromWebPageCallback( creative_search_result_ad_handler.get(), blink::mojom::WebPage::New()); + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/::testing::_)).Times(0); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrl()); + ClickRedirectUrl(), callback.Get()); } TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, @@ -249,8 +263,11 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, test::CreativeSearchResultAdMojomWebPage( /*excluded_property_names=*/{kCreativeAdRewardsValuePropertyName})); + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/::testing::_)).Times(0); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrl()); + ClickRedirectUrl(), callback.Get()); } TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, @@ -274,10 +291,15 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, EXPECT_FALSE(mojom_creative_ad->creative_set_conversion); }); - EXPECT_CALL(ads_service_mock_, - TriggerSearchResultAdEvent( - ::testing::_, mojom::SearchResultAdEventType::kClicked, - ::testing::_)); + EXPECT_CALL( + ads_service_mock_, + TriggerSearchResultAdEvent( + ::testing::_, mojom::SearchResultAdEventType::kClicked, ::testing::_)) + .WillOnce([](mojom::CreativeSearchResultAdInfoPtr /*mojom_creative_ad*/, + mojom::SearchResultAdEventType /*event_type*/, + TriggerAdEventCallback callback) { + std::move(callback).Run(/*success=*/false); + }); SimulateMaybeExtractCreativeAdPlacementIdsFromWebPageCallback( creative_search_result_ad_handler.get(), @@ -285,8 +307,11 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, /*excluded_property_names=*/{ kCreativeSetConversionUrlPatternPropertyName})); + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/false)); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrl()); + ClickRedirectUrl(), callback.Get()); } TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, @@ -322,16 +347,18 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, mojom_creative_ad); }); + int clicked_events_count = 0; + EXPECT_CALL( ads_service_mock_, TriggerSearchResultAdEvent( ::testing::_, mojom::SearchResultAdEventType::kClicked, ::testing::_)) .Times(2) .WillRepeatedly( - [&mojom_web_page]( + [&mojom_web_page, &clicked_events_count]( mojom::CreativeSearchResultAdInfoPtr mojom_creative_ad, mojom::SearchResultAdEventType /*mojom_ad_event_type*/, - TriggerAdEventCallback /*callback*/) { + TriggerAdEventCallback callback) { const CreativeSearchResultAdMap creative_search_result_ads = ExtractCreativeSearchResultAdsFromMojomWebPageEntities( mojom_web_page->entities); @@ -341,16 +368,31 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, EXPECT_EQ( creative_search_result_ads.at(test::kCreativeAdPlacementId), mojom_creative_ad); + + ++clicked_events_count; + if (clicked_events_count == 1) { + std::move(callback).Run(/*success=*/true); + } else { + std::move(callback).Run(/*success=*/false); + } }); SimulateMaybeExtractCreativeAdPlacementIdsFromWebPageCallback( creative_search_result_ad_handler.get(), mojom_web_page->Clone()); + base::MockCallback> + fist_click_callback; + EXPECT_CALL(fist_click_callback, Run(/*success=*/true)); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrl()); + ClickRedirectUrl(), fist_click_callback.Get()); + + base::MockCallback> + second_click_callback; + EXPECT_CALL(second_click_callback, Run(/*success=*/false)); creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrl()); + ClickRedirectUrl(), second_click_callback.Get()); } TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, @@ -379,14 +421,30 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, creative_search_result_ad_handler.get(), test::CreativeSearchResultAdMojomWebPage(/*excluded_property_names=*/{})); - creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - InvalidClickRedirectUrlWithNoQueryValue()); + { + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/::testing::_)).Times(0); - creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - InvalidClickRedirectUrlWithMismatchingQueryNameAndValue()); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( + InvalidClickRedirectUrlWithNoQueryValue(), callback.Get()); + } - creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - InvalidClickRedirectUrlWithNoQueryNameOrValue()); + { + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/::testing::_)).Times(0); + + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( + InvalidClickRedirectUrlWithMismatchingQueryNameAndValue(), + callback.Get()); + } + + { + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/::testing::_)).Times(0); + + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( + InvalidClickRedirectUrlWithNoQueryNameOrValue(), callback.Get()); + } } TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, @@ -433,7 +491,7 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, .WillOnce([&mojom_web_page]( mojom::CreativeSearchResultAdInfoPtr mojom_creative_ad, mojom::SearchResultAdEventType /*mojom_ad_event_type*/, - TriggerAdEventCallback /*callback*/) { + TriggerAdEventCallback callback) { const CreativeSearchResultAdMap creative_search_result_ads = ExtractCreativeSearchResultAdsFromMojomWebPageEntities( mojom_web_page->entities); @@ -444,13 +502,18 @@ TEST_F(BraveAdsCreativeSearchResultAdHandlerTest, creative_search_result_ads.at( test::kEscapedCreativeAdPlacementIdWithUnreservedCharacters), mojom_creative_ad); + + std::move(callback).Run(/*success=*/true); }); SimulateMaybeExtractCreativeAdPlacementIdsFromWebPageCallback( creative_search_result_ad_handler.get(), mojom_web_page->Clone()); + base::MockCallback> callback; + EXPECT_CALL(callback, Run(/*success=*/true)); + creative_search_result_ad_handler->MaybeTriggerCreativeAdClickedEvent( - ClickRedirectUrlWithUnreservedCharactersInPlacementId()); + ClickRedirectUrlWithUnreservedCharactersInPlacementId(), callback.Get()); } } // namespace brave_ads diff --git a/components/brave_ads/core/internal/prefs/pref_registry.cc b/components/brave_ads/core/internal/prefs/pref_registry.cc index 7b91826e0a19..169672d59aec 100644 --- a/components/brave_ads/core/internal/prefs/pref_registry.cc +++ b/components/brave_ads/core/internal/prefs/pref_registry.cc @@ -63,6 +63,9 @@ void RegisterProfilePrefs(PrefRegistrySimple* const registry) { 0.0); registry->RegisterBooleanPref(prefs::kNotificationAdDidFallbackToCustom, false); + + registry->RegisterBooleanPref(prefs::kShouldShowSearchResultAdClickedInfoBar, + true); } } // namespace brave_ads diff --git a/components/brave_ads/core/public/prefs/pref_names.h b/components/brave_ads/core/public/prefs/pref_names.h index 927d30640e42..8dfb04abefbe 100644 --- a/components/brave_ads/core/public/prefs/pref_names.h +++ b/components/brave_ads/core/public/prefs/pref_names.h @@ -68,6 +68,9 @@ inline constexpr char kNotificationAdDidFallbackToCustom[] = inline constexpr char kShouldShowOnboardingNotification[] = "brave.brave_ads.should_show_my_first_ad_notification"; +inline constexpr char kShouldShowSearchResultAdClickedInfoBar[] = + "brave.brave_ads.should_show_search_result_ad_clicked_infobar"; + // Brave stats prefs. inline constexpr char kEnabledForLastProfile[] = "brave.brave_ads.enabled_last_profile";