From df28b5bd9b6b423ea9496058675603b57cbfa878 Mon Sep 17 00:00:00 2001 From: Aleksey Seren Date: Mon, 28 Nov 2022 20:55:25 -0500 Subject: [PATCH 1/4] Search result ad click confirmation. fix https://github.com/brave/brave-browser/issues/23002 --- browser/brave_ads/ads_tab_helper.cc | 18 - browser/brave_ads/ads_tab_helper.h | 3 - browser/brave_ads/brave_ads_host.cc | 51 -- browser/brave_ads/brave_ads_host.h | 48 -- .../search_result_ad_browsertest.cc | 441 +++++++++--------- .../search_result_ad_service_factory.cc | 43 -- .../search_result_ad_service_factory.h | 51 -- .../search_result_ad_service_unittest.cc | 241 ---------- .../search_result_ad_tab_helper.cc | 138 ++++++ .../search_result_ad_tab_helper.h | 68 +++ browser/brave_ads/sources.gni | 8 +- browser/brave_content_browser_client.cc | 20 - browser/brave_tab_helpers.cc | 3 + .../chrome_content_renderer_client.cc | 9 +- components/brave_ads/common/BUILD.gn | 14 +- .../brave_ads/common/search_result_ad_util.cc | 97 ---- .../brave_ads/common/search_result_ad_util.h | 26 -- .../common/search_result_ad_util_unittest.cc | 129 ----- .../content/browser/search_result_ad/BUILD.gn | 9 +- .../content/browser/search_result_ad/DEPS | 3 +- .../search_result_ad_handler.cc | 112 +++++ .../search_result_ad_handler.h | 68 +++ .../search_result_ad_handler_unittest.cc | 187 ++++++++ .../search_result_ad_parsing_unittest.cc | 305 ------------ .../search_result_ad_service.cc | 208 --------- .../search_result_ad_service.h | 106 ----- .../core/browser/search_result_ad/BUILD.gn | 24 + .../core/browser/search_result_ad/DEPS | 4 + .../search_result_ad_parsing.cc | 198 ++++---- .../search_result_ad_parsing.h | 13 +- .../search_result_ad_parsing_unittest.cc | 193 ++++++++ .../search_result_ad/test_web_page_util.cc | 122 +++++ .../search_result_ad/test_web_page_util.h | 20 + components/brave_ads/renderer/BUILD.gn | 23 - components/brave_ads/renderer/DEPS | 8 - .../search_result_ad_renderer_throttle.cc | 128 ----- .../search_result_ad_renderer_throttle.h | 57 --- renderer/BUILD.gn | 1 - .../brave_url_loader_throttle_provider.cc | 64 --- renderer/brave_url_loader_throttle_provider.h | 50 -- renderer/sources.gni | 3 - test/BUILD.gn | 10 +- .../brave_ads/search_result_ad_broken.html | 35 +- .../brave_ads/search_result_ad_sample.html | 45 +- .../search_result_ad_with_redirect.html | 67 +++ 45 files changed, 1362 insertions(+), 2109 deletions(-) delete mode 100644 browser/brave_ads/brave_ads_host.cc delete mode 100644 browser/brave_ads/brave_ads_host.h delete mode 100644 browser/brave_ads/search_result_ad/search_result_ad_service_factory.cc delete mode 100644 browser/brave_ads/search_result_ad/search_result_ad_service_factory.h delete mode 100644 browser/brave_ads/search_result_ad/search_result_ad_service_unittest.cc create mode 100644 browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc create mode 100644 browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h delete mode 100644 components/brave_ads/common/search_result_ad_util.cc delete mode 100644 components/brave_ads/common/search_result_ad_util.h delete mode 100644 components/brave_ads/common/search_result_ad_util_unittest.cc create mode 100644 components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc create mode 100644 components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h create mode 100644 components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc delete mode 100644 components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing_unittest.cc delete mode 100644 components/brave_ads/content/browser/search_result_ad/search_result_ad_service.cc delete mode 100644 components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h create mode 100644 components/brave_ads/core/browser/search_result_ad/BUILD.gn create mode 100644 components/brave_ads/core/browser/search_result_ad/DEPS rename components/brave_ads/{content => core}/browser/search_result_ad/search_result_ad_parsing.cc (62%) rename components/brave_ads/{content => core}/browser/search_result_ad/search_result_ad_parsing.h (63%) create mode 100644 components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc create mode 100644 components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc create mode 100644 components/brave_ads/core/browser/search_result_ad/test_web_page_util.h delete mode 100644 components/brave_ads/renderer/BUILD.gn delete mode 100644 components/brave_ads/renderer/DEPS delete mode 100644 components/brave_ads/renderer/search_result_ad_renderer_throttle.cc delete mode 100644 components/brave_ads/renderer/search_result_ad_renderer_throttle.h delete mode 100644 renderer/brave_url_loader_throttle_provider.cc delete mode 100644 renderer/brave_url_loader_throttle_provider.h create mode 100644 test/data/brave_ads/search_result_ad_with_redirect.html diff --git a/browser/brave_ads/ads_tab_helper.cc b/browser/brave_ads/ads_tab_helper.cc index caf445be63a1..18f222ef34cb 100644 --- a/browser/brave_ads/ads_tab_helper.cc +++ b/browser/brave_ads/ads_tab_helper.cc @@ -8,8 +8,6 @@ #include #include "brave/browser/brave_ads/ads_service_factory.h" -#include "brave/browser/brave_ads/search_result_ad/search_result_ad_service_factory.h" -#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h" #include "chrome/browser/profiles/profile.h" #include "components/dom_distiller/content/browser/distiller_javascript_utils.h" #include "components/dom_distiller/content/browser/distiller_page_web_contents.h" @@ -45,9 +43,6 @@ AdsTabHelper::AdsTabHelper(content::WebContents* web_contents) return; } - search_result_ad_service_ = - SearchResultAdServiceFactory::GetForProfile(profile); - #if !BUILDFLAG(IS_ANDROID) BrowserList::AddObserver(this); OnBrowserSetLastActive(BrowserList::GetInstance()->GetLastActive()); @@ -128,10 +123,6 @@ void AdsTabHelper::DidFinishNavigation( redirect_chain_ = navigation_handle->GetRedirectChain(); if (!navigation_handle->IsSameDocument()) { - if (search_result_ad_service_) { - search_result_ad_service_->OnDidFinishNavigation(tab_id_); - } - should_process_ = navigation_handle->GetRestoreType() == content::RestoreType::kNotRestored; @@ -146,11 +137,6 @@ void AdsTabHelper::DidFinishNavigation( void AdsTabHelper::DocumentOnLoadCompletedInPrimaryMainFrame() { content::RenderFrameHost* render_frame_host = web_contents()->GetPrimaryMainFrame(); - if (search_result_ad_service_) { - search_result_ad_service_->MaybeRetrieveSearchResultAd( - render_frame_host, tab_id_, should_process_); - } - if (should_process_) { RunIsolatedJavaScript(render_frame_host); } @@ -207,10 +193,6 @@ void AdsTabHelper::OnVisibilityChanged(content::Visibility visibility) { } void AdsTabHelper::WebContentsDestroyed() { - if (search_result_ad_service_) { - search_result_ad_service_->OnDidCloseTab(tab_id_); - } - if (!ads_service_) { return; } diff --git a/browser/brave_ads/ads_tab_helper.h b/browser/brave_ads/ads_tab_helper.h index 3fc339d94393..88c28f9be70e 100644 --- a/browser/brave_ads/ads_tab_helper.h +++ b/browser/brave_ads/ads_tab_helper.h @@ -36,7 +36,6 @@ class DomDistillerResult; namespace brave_ads { class AdsService; -class SearchResultAdService; class AdsTabHelper : public content::WebContentsObserver, #if !BUILDFLAG(IS_ANDROID) @@ -84,8 +83,6 @@ class AdsTabHelper : public content::WebContentsObserver, SessionID tab_id_; raw_ptr ads_service_ = nullptr; // NOT OWNED - raw_ptr search_result_ad_service_ = - nullptr; // NOT OWNED bool is_active_ = false; bool is_browser_active_ = true; std::vector redirect_chain_; diff --git a/browser/brave_ads/brave_ads_host.cc b/browser/brave_ads/brave_ads_host.cc deleted file mode 100644 index 3972f7dcbfa1..000000000000 --- a/browser/brave_ads/brave_ads_host.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#include "brave/browser/brave_ads/brave_ads_host.h" - -#include - -#include "brave/browser/brave_ads/ads_service_factory.h" -#include "brave/browser/brave_ads/search_result_ad/search_result_ad_service_factory.h" -#include "brave/components/brave_ads/browser/ads_service.h" -#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h" -#include "chrome/browser/profiles/profile.h" -#include "components/sessions/content/session_tab_helper.h" -#include "content/public/browser/web_contents.h" - -namespace brave_ads { - -BraveAdsHost::BraveAdsHost(Profile* profile, content::WebContents* web_contents) - : profile_(profile), - tab_id_(sessions::SessionTabHelper::IdForTab(web_contents)) { - DCHECK(profile_); -} - -BraveAdsHost::~BraveAdsHost() = default; - -void BraveAdsHost::MaybeTriggerAdViewedEvent( - const std::string& creative_instance_id, - MaybeTriggerAdViewedEventCallback callback) { - DCHECK(callback); - DCHECK(!creative_instance_id.empty()); - - if (!tab_id_.is_valid()) { - std::move(callback).Run(/*event_triggered*/ false); - return; - } - - SearchResultAdService* search_result_ad_service = - SearchResultAdServiceFactory::GetForProfile(profile_); - - if (!search_result_ad_service) { - std::move(callback).Run(/*event_triggered*/ false); - return; - } - - search_result_ad_service->MaybeTriggerSearchResultAdViewedEvent( - creative_instance_id, tab_id_, std::move(callback)); -} - -} // namespace brave_ads diff --git a/browser/brave_ads/brave_ads_host.h b/browser/brave_ads/brave_ads_host.h deleted file mode 100644 index 3133fd75c149..000000000000 --- a/browser/brave_ads/brave_ads_host.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_BROWSER_BRAVE_ADS_BRAVE_ADS_HOST_H_ -#define BRAVE_BROWSER_BRAVE_ADS_BRAVE_ADS_HOST_H_ - -#include - -#include "base/memory/raw_ptr.h" -#include "brave/components/brave_ads/common/brave_ads_host.mojom.h" -#include "components/sessions/core/session_id.h" - -class Profile; - -namespace content { -class WebContents; -} // namespace content - -namespace brave_ads { - -// The class handles ads requests from renderer side for Desktop platforms. -class BraveAdsHost : public brave_ads::mojom::BraveAdsHost { - public: - BraveAdsHost(Profile* profile, content::WebContents* web_contents); - - BraveAdsHost(const BraveAdsHost&) = delete; - BraveAdsHost& operator=(const BraveAdsHost&) = delete; - - BraveAdsHost(BraveAdsHost&& other) noexcept = delete; - BraveAdsHost& operator=(BraveAdsHost&& other) noexcept = delete; - - ~BraveAdsHost() override; - - // brave_ads::mojom::BraveAdsHost - void MaybeTriggerAdViewedEvent( - const std::string& creative_instance_id, - MaybeTriggerAdViewedEventCallback callback) override; - - private: - raw_ptr profile_ = nullptr; - SessionID tab_id_; -}; - -} // namespace brave_ads - -#endif // BRAVE_BROWSER_BRAVE_ADS_BRAVE_ADS_HOST_H_ diff --git a/browser/brave_ads/search_result_ad/search_result_ad_browsertest.cc b/browser/brave_ads/search_result_ad/search_result_ad_browsertest.cc index 9c49df1e250a..194c75930a6d 100644 --- a/browser/brave_ads/search_result_ad/search_result_ad_browsertest.cc +++ b/browser/brave_ads/search_result_ad/search_result_ad_browsertest.cc @@ -6,27 +6,27 @@ #include #include "base/path_service.h" -#include "base/ranges/algorithm.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/test/scoped_feature_list.h" #include "bat/ads/public/interfaces/ads.mojom.h" #include "brave/browser/brave_ads/ads_service_factory.h" -#include "brave/browser/brave_ads/search_result_ad/search_result_ad_service_factory.h" +#include "brave/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h" #include "brave/components/brave_ads/browser/ads_service.h" #include "brave/components/brave_ads/browser/mock_ads_service.h" #include "brave/components/brave_ads/common/features.h" -#include "brave/components/brave_ads/common/search_result_ad_util.h" -#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h" #include "brave/components/constants/brave_paths.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" -#include "content/public/test/browser_test_utils.h" #include "content/public/test/content_mock_cert_verifier.h" -#include "content/public/test/url_loader_interceptor.h" +#include "content/public/test/test_navigation_observer.h" #include "net/dns/mock_host_resolver.h" +#include "net/http/http_status_code.h" +#include "net/test/embedded_test_server/request_handler_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -41,114 +41,34 @@ namespace { constexpr char kAllowedDomain[] = "search.brave.com"; constexpr char kNotAllowedDomain[] = "brave.com"; - -bool CheckSampleSearchAdMetadata( - const ads::mojom::SearchResultAdInfoPtr& search_result_ad, - size_t ad_index) { - const std::string index = base::StrCat({"-", base::NumberToString(ad_index)}); - if (search_result_ad->placement_id != - base::StrCat({"data-placement-id", index})) { - return false; - } - - EXPECT_EQ(search_result_ad->creative_instance_id, - base::StrCat({"data-creative-instance-id", index})); - EXPECT_EQ(search_result_ad->creative_set_id, - base::StrCat({"data-creative-set-id", index})); - EXPECT_EQ(search_result_ad->campaign_id, - base::StrCat({"data-campaign-id", index})); - EXPECT_EQ(search_result_ad->advertiser_id, - base::StrCat({"data-advertiser-id", index})); - EXPECT_EQ(search_result_ad->target_url, - GURL(base::StrCat({"https://brave.com/data-landing-page", index}))); - EXPECT_EQ(search_result_ad->headline_text, - base::StrCat({"data-headline-text", index})); - EXPECT_EQ(search_result_ad->description, - base::StrCat({"data-description", index})); - EXPECT_DOUBLE_EQ(search_result_ad->value, 0.5 + ad_index); - - EXPECT_EQ(search_result_ad->conversion->type, - base::StrCat({"data-conversion-type-value", index})); - EXPECT_EQ(search_result_ad->conversion->url_pattern, - base::StrCat({"data-conversion-url-pattern-value", index})); - EXPECT_EQ( - search_result_ad->conversion->advertiser_public_key, - base::StrCat({"data-conversion-advertiser-public-key-value", index})); - EXPECT_EQ( - static_cast(search_result_ad->conversion->observation_window), - ad_index); - - return true; -} - -brave_ads::SearchResultAdService* GetSearchResultAdService(Profile* profile) { - return brave_ads::SearchResultAdServiceFactory::GetForProfile(profile); +constexpr const char* kTargetDomains[] = {"foo.com", "bar.com"}; +constexpr char kTargetPath[] = "/simple.html"; +constexpr char kTargetPathWithRedirect[] = "/target-with-redirect"; +constexpr char kRedirectedDomain[] = "example.com"; +constexpr char kSearchResultUrlPath[] = + "/brave_ads/search_result_ad_sample.html"; +constexpr char kSearchResultWithRedirectUrlPath[] = + "/brave_ads/search_result_ad_with_redirect.html"; + +brave_ads::SearchResultAdTabHelper* GetSearchResultAdTabHelper( + Browser* browser) { + auto* web_contents = browser->tab_strip_model()->GetActiveWebContents(); + return brave_ads::SearchResultAdTabHelper::FromWebContents(web_contents); } class ScopedTestingAdsServiceSetter { public: - explicit ScopedTestingAdsServiceSetter(Profile* profile, - brave_ads::AdsService* ads_service) - : profile_(profile) { - previous_ads_service_ = - GetSearchResultAdService(profile_)->SetAdsServiceForTesting( - ads_service); + explicit ScopedTestingAdsServiceSetter(brave_ads::AdsService* ads_service) { + brave_ads::SearchResultAdTabHelper::SetAdsServiceForTesting(ads_service); } ~ScopedTestingAdsServiceSetter() { - GetSearchResultAdService(profile_)->SetAdsServiceForTesting( - previous_ads_service_.get()); + brave_ads::SearchResultAdTabHelper::SetAdsServiceForTesting(nullptr); } ScopedTestingAdsServiceSetter(const ScopedTestingAdsServiceSetter&) = delete; ScopedTestingAdsServiceSetter& operator=( const ScopedTestingAdsServiceSetter&) = delete; - - private: - raw_ptr profile_ = nullptr; - raw_ptr previous_ads_service_ = nullptr; -}; - -class SentViewedEventsWaiter final { - public: - explicit SentViewedEventsWaiter( - std::vector creative_instance_ids) { - sent_viewed_creative_instance_ids_ = std::move(creative_instance_ids); - - url_loader_interceptor_ = - std::make_unique(base::BindRepeating( - &SentViewedEventsWaiter::URLLoaderInterceptorCallback, - base::Unretained(this))); - } - ~SentViewedEventsWaiter() = default; - - bool URLLoaderInterceptorCallback( - content::URLLoaderInterceptor::RequestParams* params) { - const std::string creative_instance_id = - brave_ads::GetViewedSearchResultAdCreativeInstanceId( - params->url_request); - if (!creative_instance_id.empty()) { - auto it = base::ranges::find(sent_viewed_creative_instance_ids_, - creative_instance_id); - EXPECT_TRUE(it != sent_viewed_creative_instance_ids_.end()) - << "Not expected creative instance id: " << creative_instance_id; - if (it != sent_viewed_creative_instance_ids_.end()) { - sent_viewed_creative_instance_ids_.erase(it); - } - } - - if (sent_viewed_creative_instance_ids_.empty()) { - run_loop_.Quit(); - } - return false; - } - - void WaitForViewedEvents() { run_loop_.Run(); } - - private: - base::RunLoop run_loop_; - std::vector sent_viewed_creative_instance_ids_; - std::unique_ptr url_loader_interceptor_; }; } // namespace @@ -167,6 +87,8 @@ class SearchResultAdTest : public InProcessBrowserTest { https_server_ = std::make_unique( net::test_server::EmbeddedTestServer::TYPE_HTTPS); + https_server_->RegisterRequestHandler(base::BindRepeating( + &SearchResultAdTest::HandleRequest, base::Unretained(this))); brave::RegisterPathProvider(); base::FilePath test_data_dir; @@ -190,21 +112,48 @@ class SearchResultAdTest : public InProcessBrowserTest { InProcessBrowserTest::TearDownInProcessBrowserTestFixture(); } - content::WebContents* LoadTestDataUrl(base::StringPiece domain, - const std::string& relative_path) { - GURL url = https_server()->GetURL(domain, relative_path); + GURL GetTargetUrl(int ad_index, bool will_redirect) const { + std::string path = kTargetPath; + if (will_redirect) { + path = base::StrCat( + {kTargetPathWithRedirect, "-", base::NumberToString(ad_index)}); + } + + return https_server_->GetURL(kTargetDomains[ad_index - 1], path); + } - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_TRUE(content::NavigateToURL(web_contents, url)); - EXPECT_EQ(url, web_contents->GetVisibleURL()); + GURL GetURL(base::StringPiece domain, const std::string& path) const { + base::StringPairs replacements; + replacements.emplace_back(std::make_pair( + "REPLACE_WITH_HTTP_PORT", + base::NumberToString(https_server_->host_port_pair().port()))); - return web_contents; + std::string replaced_path = + net::test_server::GetFilePathWithReplacements(path, replacements); + return https_server_->GetURL(domain, replaced_path); } - net::EmbeddedTestServer* https_server() { return https_server_.get(); } + std::unique_ptr HandleRequest( + const net::test_server::HttpRequest& request) { + const GURL url = request.GetURL(); + const base::StringPiece path = url.path_piece(); + + if (!base::StartsWith(path, kTargetPathWithRedirect)) { + return nullptr; + } + + const GURL target_url = + https_server_->GetURL(kRedirectedDomain, kTargetPath); + + auto http_response = + std::make_unique(); + http_response->AddCustomHeader("Access-Control-Allow-Origin", "*"); + http_response->set_code(net::HTTP_MOVED_PERMANENTLY); + http_response->AddCustomHeader("Location", target_url.spec()); + return http_response; + } - Profile* profile() { return browser()->profile(); } + net::EmbeddedTestServer* https_server() { return https_server_.get(); } private: base::test::ScopedFeatureList feature_list_; @@ -212,146 +161,198 @@ class SearchResultAdTest : public InProcessBrowserTest { std::unique_ptr https_server_; }; -IN_PROC_BROWSER_TEST_F(SearchResultAdTest, SampleSearchAdMetadata) { - brave_ads::MockAdsService ads_service; - ScopedTestingAdsServiceSetter scoped_setter(profile(), &ads_service); - - EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(true)); - auto run_loop1 = std::make_unique(); - auto run_loop2 = std::make_unique(); - EXPECT_CALL(ads_service, TriggerSearchResultAdEvent(_, _)) - .Times(2) - .WillRepeatedly( - [&run_loop1, &run_loop2]( - ads::mojom::SearchResultAdInfoPtr ad_mojom, - const ads::mojom::SearchResultAdEventType event_type) { - const bool is_search_result_ad_1 = - CheckSampleSearchAdMetadata(ad_mojom, 1); - const bool is_search_result_ad_2 = - CheckSampleSearchAdMetadata(ad_mojom, 2); - EXPECT_TRUE(is_search_result_ad_1 || is_search_result_ad_2); - - if (is_search_result_ad_1) { - run_loop1->Quit(); - } else if (is_search_result_ad_2) { - run_loop2->Quit(); - } - }); - - SentViewedEventsWaiter sent_viewed_events_waiter( - {"data-creative-instance-id-1", "not-existant"}); - LoadTestDataUrl(kAllowedDomain, "/brave_ads/search_result_ad_sample.html"); - - run_loop1->Run(); - run_loop2->Run(); - sent_viewed_events_waiter.WaitForViewedEvents(); -} - IN_PROC_BROWSER_TEST_F(SearchResultAdTest, AdsDisabled) { brave_ads::MockAdsService ads_service; - ScopedTestingAdsServiceSetter scoped_setter(profile(), &ads_service); + ScopedTestingAdsServiceSetter scoped_setter(&ads_service); EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(false)); EXPECT_CALL(ads_service, TriggerSearchResultAdEvent(_, _)).Times(0); - base::RunLoop run_loop; - GetSearchResultAdService(profile()) - ->SetMetadataRequestFinishedCallbackForTesting(base::BindOnce( - [](base::OnceClosure run_loop_closure) { - std::move(run_loop_closure).Run(); - }, - run_loop.QuitClosure())); - - SentViewedEventsWaiter sent_viewed_events_waiter( - {"data-creative-instance-id-1", "data-creative-instance-id-1", - "data-creative-instance-id-2", "not-existant"}); - LoadTestDataUrl(kAllowedDomain, "/brave_ads/search_result_ad_sample.html"); - - run_loop.Run(); - sent_viewed_events_waiter.WaitForViewedEvents(); + GURL url = GetURL(kAllowedDomain, kSearchResultUrlPath); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_EQ(url, web_contents->GetVisibleURL()); } IN_PROC_BROWSER_TEST_F(SearchResultAdTest, NotAllowedDomain) { brave_ads::MockAdsService ads_service; - ScopedTestingAdsServiceSetter scoped_setter(profile(), &ads_service); + ScopedTestingAdsServiceSetter scoped_setter(&ads_service); EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(true)); EXPECT_CALL(ads_service, TriggerSearchResultAdEvent(_, _)).Times(0); - base::RunLoop run_loop; - GetSearchResultAdService(profile()) - ->SetMetadataRequestFinishedCallbackForTesting(base::BindOnce( - [](base::OnceClosure run_loop_closure) { - std::move(run_loop_closure).Run(); - }, - run_loop.QuitClosure())); - - SentViewedEventsWaiter sent_viewed_events_waiter( - {"data-creative-instance-id-1", "data-creative-instance-id-1", - "data-creative-instance-id-2", "not-existant"}); - LoadTestDataUrl(kNotAllowedDomain, "/brave_ads/search_result_ad_sample.html"); - - run_loop.Run(); - sent_viewed_events_waiter.WaitForViewedEvents(); + GURL url = GetURL(kNotAllowedDomain, kSearchResultUrlPath); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_EQ(url, web_contents->GetVisibleURL()); } -IN_PROC_BROWSER_TEST_F(SearchResultAdTest, NoSearchAdMetadata) { +IN_PROC_BROWSER_TEST_F(SearchResultAdTest, BrokenSearchAdMetadata) { brave_ads::MockAdsService ads_service; - ScopedTestingAdsServiceSetter scoped_setter(profile(), &ads_service); + ScopedTestingAdsServiceSetter scoped_setter(&ads_service); EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(true)); EXPECT_CALL(ads_service, TriggerSearchResultAdEvent(_, _)).Times(0); - base::RunLoop run_loop; - GetSearchResultAdService(profile()) - ->SetMetadataRequestFinishedCallbackForTesting(base::BindOnce( - [](base::OnceClosure run_loop_closure) { - std::move(run_loop_closure).Run(); - }, - run_loop.QuitClosure())); + GURL url = GetURL(kAllowedDomain, "/brave_ads/search_result_ad_broken.html"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_EQ(url, web_contents->GetVisibleURL()); +} - LoadTestDataUrl(kAllowedDomain, "/simple.html"); +IN_PROC_BROWSER_TEST_F(SearchResultAdTest, IncognitoBrowser) { + GURL url = GetURL(kAllowedDomain, kSearchResultUrlPath); + Browser* incognito_browser = OpenURLOffTheRecord(browser()->profile(), url); + EXPECT_FALSE(GetSearchResultAdTabHelper(incognito_browser)); - run_loop.Run(); + ASSERT_TRUE(ui_test_utils::NavigateToURL(incognito_browser, url)); + content::WebContents* web_contents = + incognito_browser->tab_strip_model()->GetActiveWebContents(); + EXPECT_EQ(url, web_contents->GetVisibleURL()); + + content::CreateAndLoadWebContentsObserver observer; + EXPECT_TRUE(content::ExecJs(web_contents, + "document.getElementById('ad_link_2').click();")); + observer.Wait(); } -IN_PROC_BROWSER_TEST_F(SearchResultAdTest, BrokenSearchAdMetadata) { - brave_ads::MockAdsService ads_service; - ScopedTestingAdsServiceSetter scoped_setter(profile(), &ads_service); +class SampleSearchResultAdTest : public SearchResultAdTest, + public testing::WithParamInterface { + public: + bool IsRedirecting() const { return GetParam(); } - EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(true)); - EXPECT_CALL(ads_service, TriggerSearchResultAdEvent(_, _)).Times(0); + GURL GetSearchResultUrl() const { + return GetURL(kAllowedDomain, IsRedirecting() + ? kSearchResultWithRedirectUrlPath + : kSearchResultUrlPath); + } - base::RunLoop run_loop; - GetSearchResultAdService(profile()) - ->SetMetadataRequestFinishedCallbackForTesting(base::BindOnce( - [](base::OnceClosure run_loop_closure) { - std::move(run_loop_closure).Run(); - }, - run_loop.QuitClosure())); + bool CheckSampleSearchAdMetadata( + const ads::mojom::SearchResultAdInfoPtr& search_result_ad, + size_t ad_index) { + const std::string index = + base::StrCat({"-", base::NumberToString(ad_index)}); + if (search_result_ad->placement_id != + base::StrCat({"data-placement-id", index})) { + return false; + } - SentViewedEventsWaiter sent_viewed_events_waiter( - {"data-creative-instance-id-1"}); - LoadTestDataUrl(kAllowedDomain, "/brave_ads/search_result_ad_broken.html"); + EXPECT_EQ(search_result_ad->creative_instance_id, + base::StrCat({"data-creative-instance-id", index})); + EXPECT_EQ(search_result_ad->creative_set_id, + base::StrCat({"data-creative-set-id", index})); + EXPECT_EQ(search_result_ad->campaign_id, + base::StrCat({"data-campaign-id", index})); + EXPECT_EQ(search_result_ad->advertiser_id, + base::StrCat({"data-advertiser-id", index})); + EXPECT_EQ(search_result_ad->target_url, + GetTargetUrl(ad_index, IsRedirecting())); + EXPECT_EQ(search_result_ad->headline_text, + base::StrCat({"data-headline-text", index})); + EXPECT_EQ(search_result_ad->description, + base::StrCat({"data-description", index})); + EXPECT_DOUBLE_EQ(search_result_ad->value, 0.5 + ad_index); + + EXPECT_EQ(search_result_ad->conversion->type, + base::StrCat({"data-conversion-type-value", index})); + EXPECT_EQ(search_result_ad->conversion->url_pattern, + base::StrCat({"data-conversion-url-pattern-value", index})); + EXPECT_EQ( + search_result_ad->conversion->advertiser_public_key, + base::StrCat({"data-conversion-advertiser-public-key-value", index})); + EXPECT_EQ( + static_cast(search_result_ad->conversion->observation_window), + ad_index); + + return true; + } + + content::WebContents* LoadAndCheckSampleSearchResultAdWebPage( + brave_ads::MockAdsService* ads_service, + const GURL& url) { + auto run_loop1 = std::make_unique(); + auto run_loop2 = std::make_unique(); + EXPECT_CALL(*ads_service, TriggerSearchResultAdEvent(_, _)) + .Times(2) + .WillRepeatedly( + [this, &run_loop1, &run_loop2]( + ads::mojom::SearchResultAdInfoPtr ad_mojom, + const ads::mojom::SearchResultAdEventType event_type) { + const bool is_search_result_ad_1 = + CheckSampleSearchAdMetadata(ad_mojom, 1); + const bool is_search_result_ad_2 = + CheckSampleSearchAdMetadata(ad_mojom, 2); + EXPECT_TRUE(is_search_result_ad_1 || is_search_result_ad_2); + + if (is_search_result_ad_1) { + run_loop1->Quit(); + } else if (is_search_result_ad_2) { + run_loop2->Quit(); + } + }); + + EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_EQ(url, web_contents->GetVisibleURL()); + run_loop1->Run(); + run_loop2->Run(); + + return web_contents; + } +}; + +IN_PROC_BROWSER_TEST_P(SampleSearchResultAdTest, + SearchResultAdOpenedInSameTab) { + brave_ads::MockAdsService ads_service; + ScopedTestingAdsServiceSetter scoped_setter(&ads_service); + EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(true)); + + content::WebContents* web_contents = LoadAndCheckSampleSearchResultAdWebPage( + &ads_service, GetSearchResultUrl()); + + base::RunLoop run_loop; + EXPECT_CALL(ads_service, TriggerSearchResultAdEvent(_, _)) + .WillOnce([this, &run_loop]( + ads::mojom::SearchResultAdInfoPtr ad_mojom, + const ads::mojom::SearchResultAdEventType event_type) { + EXPECT_EQ(event_type, ads::mojom::SearchResultAdEventType::kClicked); + CheckSampleSearchAdMetadata(ad_mojom, 1); + run_loop.Quit(); + }); + + EXPECT_TRUE(content::ExecJs(web_contents, + "document.getElementById('ad_link_1').click();")); run_loop.Run(); - sent_viewed_events_waiter.WaitForViewedEvents(); } -IN_PROC_BROWSER_TEST_F(SearchResultAdTest, IncognitoBrowser) { - SentViewedEventsWaiter sent_viewed_events_waiter( - {"data-creative-instance-id-1", "data-creative-instance-id-1", - "data-creative-instance-id-2", "not-existant"}); - - GURL url = https_server()->GetURL(kAllowedDomain, - "/brave_ads/search_result_ad_sample.html"); - Browser* incognito_browser = OpenURLOffTheRecord(browser()->profile(), url); - EXPECT_FALSE(GetSearchResultAdService(incognito_browser->profile())); +IN_PROC_BROWSER_TEST_P(SampleSearchResultAdTest, SearchResultAdOpenedInNewTab) { + brave_ads::MockAdsService ads_service; + ScopedTestingAdsServiceSetter scoped_setter(&ads_service); + EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(true)); - content::WebContents* web_contents = - incognito_browser->tab_strip_model()->GetActiveWebContents(); - EXPECT_TRUE(content::NavigateToURL(web_contents, url)); - EXPECT_EQ(url, web_contents->GetVisibleURL()); + content::WebContents* web_contents = LoadAndCheckSampleSearchResultAdWebPage( + &ads_service, GetSearchResultUrl()); - sent_viewed_events_waiter.WaitForViewedEvents(); + EXPECT_CALL(ads_service, IsEnabled()).WillRepeatedly(Return(true)); + base::RunLoop run_loop; + EXPECT_CALL(ads_service, TriggerSearchResultAdEvent(_, _)) + .WillOnce([this, &run_loop]( + ads::mojom::SearchResultAdInfoPtr ad_mojom, + const ads::mojom::SearchResultAdEventType event_type) { + EXPECT_EQ(event_type, ads::mojom::SearchResultAdEventType::kClicked); + CheckSampleSearchAdMetadata(ad_mojom, 2); + run_loop.Quit(); + }); + + EXPECT_TRUE(content::ExecJs(web_contents, + "document.getElementById('ad_link_2').click();")); + run_loop.Run(); } + +INSTANTIATE_TEST_SUITE_P(, SampleSearchResultAdTest, testing::Bool()); diff --git a/browser/brave_ads/search_result_ad/search_result_ad_service_factory.cc b/browser/brave_ads/search_result_ad/search_result_ad_service_factory.cc deleted file mode 100644 index a919fbf90a6b..000000000000 --- a/browser/brave_ads/search_result_ad/search_result_ad_service_factory.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2022 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/search_result_ad/search_result_ad_service_factory.h" - -#include "brave/browser/brave_ads/ads_service_factory.h" -#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h" -#include "chrome/browser/profiles/profile.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" - -namespace brave_ads { - -// static -SearchResultAdService* SearchResultAdServiceFactory::GetForProfile( - Profile* profile) { - return static_cast( - GetInstance()->GetServiceForBrowserContext(profile, /*create*/ true)); -} - -// static -SearchResultAdServiceFactory* SearchResultAdServiceFactory::GetInstance() { - return base::Singleton::get(); -} - -SearchResultAdServiceFactory::SearchResultAdServiceFactory() - : BrowserContextKeyedServiceFactory( - "SearchResultAdService", - BrowserContextDependencyManager::GetInstance()) { - DependsOn(AdsServiceFactory::GetInstance()); -} - -SearchResultAdServiceFactory::~SearchResultAdServiceFactory() = default; - -KeyedService* SearchResultAdServiceFactory::BuildServiceInstanceFor( - content::BrowserContext* context) const { - Profile* profile = Profile::FromBrowserContext(context); - AdsService* ads_service = AdsServiceFactory::GetForProfile(profile); - return new SearchResultAdService(ads_service); -} - -} // namespace brave_ads diff --git a/browser/brave_ads/search_result_ad/search_result_ad_service_factory.h b/browser/brave_ads/search_result_ad/search_result_ad_service_factory.h deleted file mode 100644 index 6eefd847dd30..000000000000 --- a/browser/brave_ads/search_result_ad/search_result_ad_service_factory.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2022 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_SEARCH_RESULT_AD_SEARCH_RESULT_AD_SERVICE_FACTORY_H_ -#define BRAVE_BROWSER_BRAVE_ADS_SEARCH_RESULT_AD_SEARCH_RESULT_AD_SERVICE_FACTORY_H_ - -#include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" - -class Profile; - -namespace content { -class BrowserContext; -} // namespace content - -namespace brave_ads { - -class SearchResultAdService; - -class SearchResultAdServiceFactory : public BrowserContextKeyedServiceFactory { - public: - SearchResultAdServiceFactory(const SearchResultAdServiceFactory&) = delete; - SearchResultAdServiceFactory& operator=(const SearchResultAdServiceFactory&) = - delete; - - SearchResultAdServiceFactory(SearchResultAdServiceFactory&& other) noexcept = - delete; - SearchResultAdServiceFactory& operator=( - SearchResultAdServiceFactory&& other) noexcept = delete; - - static SearchResultAdService* GetForProfile(Profile* profile); - - static SearchResultAdServiceFactory* GetInstance(); - - private: - friend struct base::DefaultSingletonTraits; - - SearchResultAdServiceFactory(); - - ~SearchResultAdServiceFactory() override; - - // BrowserContextKeyedServiceFactory: - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const override; -}; - -} // namespace brave_ads - -#endif // BRAVE_BROWSER_BRAVE_ADS_SEARCH_RESULT_AD_SEARCH_RESULT_AD_SERVICE_FACTORY_H_ diff --git a/browser/brave_ads/search_result_ad/search_result_ad_service_unittest.cc b/browser/brave_ads/search_result_ad/search_result_ad_service_unittest.cc deleted file mode 100644 index e4adfb947abc..000000000000 --- a/browser/brave_ads/search_result_ad/search_result_ad_service_unittest.cc +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright (c) 2022 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/content/browser/search_result_ad/search_result_ad_service.h" -#include "base/test/scoped_feature_list.h" -#include "brave/components/brave_ads/browser/mock_ads_service.h" -#include "brave/components/brave_ads/common/features.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "components/sessions/core/session_id.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -using testing::Return; - -namespace { - -constexpr char kAllowedDomain[] = "https://search.brave.com"; -constexpr char kNotAllowedDomain[] = "https://brave.com"; - -class SearchResultAdServiceTest : public ChromeRenderViewHostTestHarness { - public: - SearchResultAdServiceTest() { - feature_list_.InitAndEnableFeature( - brave_ads::features::kSupportBraveSearchResultAdConfirmationEvents); - search_result_ad_service_ = - std::make_unique(&ads_service_); - } - ~SearchResultAdServiceTest() override = default; - - SearchResultAdServiceTest(const SearchResultAdServiceTest&) = delete; - SearchResultAdServiceTest& operator=(const SearchResultAdServiceTest&) = - delete; - - protected: - brave_ads::MockAdsService ads_service_; - std::unique_ptr search_result_ad_service_; - base::test::ScopedFeatureList feature_list_; -}; - -TEST_F(SearchResultAdServiceTest, BraveAdsDisabledTryTriggerAd) { - EXPECT_CALL(ads_service_, IsEnabled()).WillOnce(Return(false)); - - SessionID session_id = SessionID::NewUnique(); - NavigateAndCommit(GURL(kAllowedDomain)); - search_result_ad_service_->OnDidFinishNavigation(session_id); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, NotAllowedDomainTryTriggerAdBeforeRetrieve) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - NavigateAndCommit(GURL(kNotAllowedDomain)); - search_result_ad_service_->OnDidFinishNavigation(session_id); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - search_result_ad_service_->MaybeRetrieveSearchResultAd(main_rfh(), session_id, - true); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, NotAllowedDomainTryTriggerAdAfterRetrieve) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - NavigateAndCommit(GURL(kNotAllowedDomain)); - search_result_ad_service_->OnDidFinishNavigation(session_id); - - search_result_ad_service_->MaybeRetrieveSearchResultAd(main_rfh(), session_id, - true); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, TabRestoredTryTriggerAdBeforeRetrieve) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - NavigateAndCommit(GURL(kAllowedDomain)); - search_result_ad_service_->OnDidFinishNavigation(session_id); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - search_result_ad_service_->MaybeRetrieveSearchResultAd(main_rfh(), session_id, - false); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, TabRestoredTryTriggerAdAfterRetrieve) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - NavigateAndCommit(GURL(kAllowedDomain)); - search_result_ad_service_->OnDidFinishNavigation(session_id); - - search_result_ad_service_->MaybeRetrieveSearchResultAd(main_rfh(), session_id, - false); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, UnknownTabTryTriggerAd) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, TryTriggerAdRepeatedNavigation) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - // Simulate navigation was finished. - search_result_ad_service_->OnDidFinishNavigation(session_id); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - // Simulate navigation. - search_result_ad_service_->OnDidFinishNavigation(session_id); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, TryTriggerAdBeforeTabDeleted) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - // Simulate navigation was finished. - search_result_ad_service_->OnDidFinishNavigation(session_id); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - // Simulate tab deletion before search result JSON-ln loading. - search_result_ad_service_->OnDidCloseTab(session_id); - - run_loop.Run(); -} - -TEST_F(SearchResultAdServiceTest, TryTriggerAdAfterTabDeleted) { - EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); - - SessionID session_id = SessionID::NewUnique(); - // Simulate navigation was finished. - search_result_ad_service_->OnDidFinishNavigation(session_id); - // Simulate tab deletion before search result JSON-ln loading. - search_result_ad_service_->OnDidCloseTab(session_id); - - base::RunLoop run_loop; - search_result_ad_service_->MaybeTriggerSearchResultAdViewedEvent( - "creative_instance_id", session_id, - base::BindOnce( - [](base::RunLoop* run_loop, bool ad_was_triggered) { - EXPECT_FALSE(ad_was_triggered); - run_loop->Quit(); - }, - base::Unretained(&run_loop))); - - run_loop.Run(); -} - -} // namespace diff --git a/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc new file mode 100644 index 000000000000..66d9187f225a --- /dev/null +++ b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc @@ -0,0 +1,138 @@ +/* Copyright (c) 2022 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/search_result_ad/search_result_ad_tab_helper.h" + +#include "base/feature_list.h" +#include "brave/browser/brave_ads/ads_service_factory.h" +#include "brave/components/brave_ads/browser/ads_service.h" +#include "brave/components/brave_ads/common/features.h" +#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h" +#include "brave/components/brave_search/common/brave_search_utils.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" + +namespace brave_ads { + +namespace { + +AdsService* g_ads_service_for_testing = nullptr; + +} // namespace + +SearchResultAdTabHelper::SearchResultAdTabHelper( + content::WebContents* web_contents) + : WebContentsObserver(web_contents), + content::WebContentsUserData(*web_contents) {} + +SearchResultAdTabHelper::~SearchResultAdTabHelper() = default; + +// static +void SearchResultAdTabHelper::MaybeCreateForWebContents( + content::WebContents* web_contents) { + DCHECK(web_contents); + if (!base::FeatureList::IsEnabled( + features::kSupportBraveSearchResultAdConfirmationEvents) || + !web_contents->GetBrowserContext() || + web_contents->GetBrowserContext()->IsOffTheRecord()) { + return; + } + CreateForWebContents(web_contents); +} + +void SearchResultAdTabHelper::MaybeTriggerSearchResultAdClickedEvent( + const GURL& navigation_url) { + if (search_result_ad_handler_) { + search_result_ad_handler_->MaybeTriggerSearchResultAdClickedEvent( + navigation_url); + } +} + +// static +void SearchResultAdTabHelper::SetAdsServiceForTesting(AdsService* ads_service) { + g_ads_service_for_testing = ads_service; +} + +AdsService* SearchResultAdTabHelper::GetAdsService() { + if (g_ads_service_for_testing) { + return g_ads_service_for_testing; + } + + Profile* profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + return AdsServiceFactory::GetForProfile(profile); +} + +void SearchResultAdTabHelper::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInPrimaryMainFrame() || + !navigation_handle->HasCommitted() || + navigation_handle->IsSameDocument()) { + return; + } + + ProcessPossibleSearchResultAdClickedEvent(navigation_handle); + + const bool should_trigger_viewed_event = + navigation_handle->GetRestoreType() == content::RestoreType::kNotRestored; + search_result_ad_handler_ = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + GetAdsService(), navigation_handle->GetURL(), + should_trigger_viewed_event); +} + +void SearchResultAdTabHelper::DocumentOnLoadCompletedInPrimaryMainFrame() { + content::RenderFrameHost* render_frame_host = + web_contents()->GetPrimaryMainFrame(); + if (search_result_ad_handler_) { + search_result_ad_handler_->MaybeRetrieveSearchResultAd(render_frame_host); + } +} + +void SearchResultAdTabHelper::WebContentsDestroyed() { + search_result_ad_handler_.reset(); +} + +void SearchResultAdTabHelper::ProcessPossibleSearchResultAdClickedEvent( + content::NavigationHandle* navigation_handle) { + DCHECK(navigation_handle); + + const auto& initiator_origin = navigation_handle->GetInitiatorOrigin(); + if (!navigation_handle->IsInPrimaryMainFrame() || + !ui::PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(), + ui::PAGE_TRANSITION_LINK) || + !initiator_origin || + !brave_search::IsAllowedHost(initiator_origin->GetURL())) { + return; + } + + content::WebContents* search_result_ad_web_contents = + navigation_handle->GetWebContents(); + if (!search_result_ad_web_contents) { + return; + } + + if (content::WebContents* original_web_contents = + search_result_ad_web_contents + ->GetFirstWebContentsInLiveOriginalOpenerChain()) { + search_result_ad_web_contents = original_web_contents; + } + + SearchResultAdTabHelper* search_result_ad_tab_helper = + SearchResultAdTabHelper::FromWebContents(search_result_ad_web_contents); + if (!search_result_ad_tab_helper) { + return; + } + + DCHECK(!navigation_handle->GetRedirectChain().empty()); + const GURL target_url = navigation_handle->GetRedirectChain()[0]; + search_result_ad_tab_helper->MaybeTriggerSearchResultAdClickedEvent( + target_url); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(SearchResultAdTabHelper); + +} // namespace brave_ads diff --git a/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h new file mode 100644 index 000000000000..97cdc1bd49b9 --- /dev/null +++ b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2022 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_SEARCH_RESULT_AD_SEARCH_RESULT_AD_TAB_HELPER_H_ +#define BRAVE_BROWSER_BRAVE_ADS_SEARCH_RESULT_AD_SEARCH_RESULT_AD_TAB_HELPER_H_ + +#include +#include + +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" +#include "url/gurl.h" + +namespace content { +class RenderFrameHost; +} + +namespace brave_ads { + +class AdsService; +class SearchResultAdHandler; + +class SearchResultAdTabHelper + : public content::WebContentsObserver, + public content::WebContentsUserData { + public: + explicit SearchResultAdTabHelper(content::WebContents* web_contents); + ~SearchResultAdTabHelper() override; + + SearchResultAdTabHelper(const SearchResultAdTabHelper&) = delete; + SearchResultAdTabHelper& operator=(const SearchResultAdTabHelper&) = delete; + + static void MaybeCreateForWebContents(content::WebContents* web_contents); + + void MaybeRetrieveSearchResultAd(content::RenderFrameHost* render_frame_host, + bool should_trigger_viewed_event); + + void MaybeTriggerSearchResultAdClickedEvent(const GURL& navigation_url); + + static void SetAdsServiceForTesting(AdsService* ads_service); + + private: + friend class content::WebContentsUserData; + + AdsService* GetAdsService(); + + // content::WebContentsObserver overrides + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + void DocumentOnLoadCompletedInPrimaryMainFrame() override; + void WebContentsDestroyed() override; + + void ProcessPossibleSearchResultAdClickedEvent( + content::NavigationHandle* navigation_handle); + + std::unique_ptr search_result_ad_handler_; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +} // namespace brave_ads + +#endif // BRAVE_BROWSER_BRAVE_ADS_SEARCH_RESULT_AD_SEARCH_RESULT_AD_TAB_HELPER_H_ diff --git a/browser/brave_ads/sources.gni b/browser/brave_ads/sources.gni index eb564dcf8499..4179657de24d 100644 --- a/browser/brave_ads/sources.gni +++ b/browser/brave_ads/sources.gni @@ -12,8 +12,6 @@ brave_browser_brave_ads_sources = [ "//brave/browser/brave_ads/background_helper/background_helper.h", "//brave/browser/brave_ads/background_helper/background_helper_holder.cc", "//brave/browser/brave_ads/background_helper/background_helper_holder.h", - "//brave/browser/brave_ads/brave_ads_host.cc", - "//brave/browser/brave_ads/brave_ads_host.h", "//brave/browser/brave_ads/brave_stats_updater_helper.cc", "//brave/browser/brave_ads/brave_stats_updater_helper.h", "//brave/browser/brave_ads/notification_helper/notification_helper.cc", @@ -21,8 +19,8 @@ brave_browser_brave_ads_sources = [ "//brave/browser/brave_ads/notification_helper/notification_helper_impl.cc", "//brave/browser/brave_ads/notification_helper/notification_helper_impl.h", "//brave/browser/brave_ads/notifications/notification_ad_platform_bridge.h", - "//brave/browser/brave_ads/search_result_ad/search_result_ad_service_factory.cc", - "//brave/browser/brave_ads/search_result_ad/search_result_ad_service_factory.h", + "//brave/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc", + "//brave/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h", ] brave_browser_brave_ads_deps = [ @@ -33,7 +31,6 @@ brave_browser_brave_ads_deps = [ "//brave/browser/ui/brave_ads", "//brave/components/brave_ads/browser", "//brave/components/brave_ads/common", - "//brave/components/brave_ads/common:mojom", "//brave/components/brave_ads/content/browser/search_result_ad", "//brave/components/brave_federated", "//brave/components/brave_federated/public/interfaces", @@ -47,6 +44,7 @@ brave_browser_brave_ads_deps = [ "//components/keyed_service/content", "//components/sessions", "//content/public/browser", + "//services/network/public/cpp", "//ui/base", ] diff --git a/browser/brave_content_browser_client.cc b/browser/brave_content_browser_client.cc index 98ad74cf5d1d..849a42d70622 100644 --- a/browser/brave_content_browser_client.cc +++ b/browser/brave_content_browser_client.cc @@ -15,7 +15,6 @@ #include "base/strings/strcat.h" #include "base/system/sys_info.h" #include "brave/browser/brave_ads/ads_service_factory.h" -#include "brave/browser/brave_ads/brave_ads_host.h" #include "brave/browser/brave_browser_main_extra_parts.h" #include "brave/browser/brave_browser_process.h" #include "brave/browser/brave_shields/brave_shields_web_contents_observer.h" @@ -236,19 +235,6 @@ void BindCosmeticFiltersResourcesOnTaskRunner( std::move(receiver)); } -void BindBraveAdsHost( - content::RenderFrameHost* const frame_host, - mojo::PendingReceiver receiver) { - auto* context = frame_host->GetBrowserContext(); - auto* profile = Profile::FromBrowserContext(context); - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost(frame_host); - - mojo::MakeSelfOwnedReceiver( - std::make_unique(profile, web_contents), - std::move(receiver)); -} - void BindCosmeticFiltersResources( content::RenderFrameHost* const frame_host, mojo::PendingReceiver @@ -577,12 +563,6 @@ void BraveContentBrowserClient::RegisterBrowserInterfaceBindersForFrame( base::BindRepeating(&BindBraveSearchDefaultHost)); } - if (base::FeatureList::IsEnabled( - brave_ads::features::kSupportBraveSearchResultAdConfirmationEvents)) { - map->Add( - base::BindRepeating(&BindBraveAdsHost)); - } - map->Add( base::BindRepeating(&MaybeBindWalletP3A)); if (brave_wallet::IsAllowedForContext( diff --git a/browser/brave_tab_helpers.cc b/browser/brave_tab_helpers.cc index b366925d305f..7ca359f45ff9 100644 --- a/browser/brave_tab_helpers.cc +++ b/browser/brave_tab_helpers.cc @@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/feature_list.h" #include "brave/browser/brave_ads/ads_tab_helper.h" +#include "brave/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h" #include "brave/browser/brave_news/brave_news_tab_helper.h" #include "brave/browser/brave_rewards/rewards_tab_helper.h" #include "brave/browser/brave_shields/brave_shields_web_contents_observer.h" @@ -102,6 +103,8 @@ void AttachTabHelpers(content::WebContents* web_contents) { brave_ads::AdsTabHelper::CreateForWebContents(web_contents); + brave_ads::SearchResultAdTabHelper::MaybeCreateForWebContents(web_contents); + #if BUILDFLAG(ENABLE_EXTENSIONS) WebDiscoveryTabHelper::MaybeCreateForWebContents(web_contents); #endif diff --git a/chromium_src/chrome/renderer/chrome_content_renderer_client.cc b/chromium_src/chrome/renderer/chrome_content_renderer_client.cc index a9ae8c98d074..cdd2ff7765a0 100644 --- a/chromium_src/chrome/renderer/chrome_content_renderer_client.cc +++ b/chromium_src/chrome/renderer/chrome_content_renderer_client.cc @@ -1,15 +1,11 @@ -/* Copyright 2020 The Brave Authors. All rights reserved. +/* 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 http://mozilla.org/MPL/2.0/. */ + * You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "brave/components/content_settings/renderer/brave_content_settings_agent_impl.h" -#include "brave/renderer/brave_url_loader_throttle_provider.h" -#include "chrome/renderer/url_loader_throttle_provider_impl.h" #include "components/feed/content/renderer/rss_link_reader.h" -#define URLLoaderThrottleProviderImpl BraveURLLoaderThrottleProvider - // We need to do this here rather than in |BraveContentRendererClient| because // it needs access to the registry on ChromeRenderFrameObserver. #define BRAVE_RENDER_FRAME_CREATED \ @@ -18,4 +14,3 @@ #include "src/chrome/renderer/chrome_content_renderer_client.cc" #undef BRAVE_RENDER_FRAME_CREATED -#undef URLLoaderThrottleProviderImpl diff --git a/components/brave_ads/common/BUILD.gn b/components/brave_ads/common/BUILD.gn index 3003013f8839..1ae463c93258 100644 --- a/components/brave_ads/common/BUILD.gn +++ b/components/brave_ads/common/BUILD.gn @@ -5,12 +5,6 @@ import("//mojo/public/tools/bindings/mojom.gni") -mojom("mojom") { - sources = [ "brave_ads_host.mojom" ] - - deps = [ "//mojo/public/mojom/base" ] -} - static_library("common") { sources = [ "constants.h", @@ -18,13 +12,7 @@ static_library("common") { "features.h", "pref_names.cc", "pref_names.h", - "search_result_ad_util.cc", - "search_result_ad_util.h", ] - deps = [ - "//base", - "//services/network/public/cpp", - "//url", - ] + deps = [ "//base" ] } diff --git a/components/brave_ads/common/search_result_ad_util.cc b/components/brave_ads/common/search_result_ad_util.cc deleted file mode 100644 index c08652310e03..000000000000 --- a/components/brave_ads/common/search_result_ad_util.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (c) 2022 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/common/search_result_ad_util.h" - -#include "base/containers/contains.h" -#include "base/containers/fixed_flat_set.h" -#include "base/json/json_reader.h" -#include "base/strings/string_piece.h" -#include "base/values.h" -#include "services/network/public/cpp/resource_request.h" -#include "url/gurl.h" - -namespace brave_ads { - -namespace { - -constexpr auto kSearchResultAdsConfirmationVettedHosts = - base::MakeFixedFlatSet( - {"search.anonymous.brave.com", "search.anonymous.bravesoftware.com"}); -constexpr char kSearchResultAdsViewedPath[] = "/v3/confirmation"; -constexpr char kCreativeInstanceIdParameterName[] = "creativeInstanceId"; -constexpr char kTypeParameterName[] = "type"; -constexpr char kTypeViewParameterValue[] = "view"; - -bool IsSearchResultAdConfirmationUrl(const GURL& url, base::StringPiece path) { - if (!url.is_valid() || !url.SchemeIs(url::kHttpsScheme) || - url.path_piece() != path) { - return false; - } - - if (!base::Contains(kSearchResultAdsConfirmationVettedHosts, - url.host_piece())) { - return false; - } - - return true; -} - -std::string GetUploadData(const network::ResourceRequest& request) { - std::string upload_data; - if (!request.request_body) { - return {}; - } - const auto* elements = request.request_body->elements(); - for (const network::DataElement& element : *elements) { - if (element.type() == network::mojom::DataElementDataView::Tag::kBytes) { - const auto& bytes = element.As().bytes(); - upload_data.append(bytes.cbegin(), bytes.cend()); - } - } - - return upload_data; -} - -} // namespace - -bool IsSearchResultAdViewedConfirmationUrl(const GURL& url) { - return IsSearchResultAdConfirmationUrl(url, kSearchResultAdsViewedPath); -} - -std::string GetViewedSearchResultAdCreativeInstanceId( - const network::ResourceRequest& request) { - if (!IsSearchResultAdViewedConfirmationUrl(request.url) || - request.method != net::HttpRequestHeaders::kPostMethod) { - return {}; - } - - const std::string payload_json = GetUploadData(request); - const absl::optional payload_value = - base::JSONReader::Read(payload_json); - if (!payload_value) { - return {}; - } - - const base::Value::Dict* const payload_dict = payload_value->GetIfDict(); - if (!payload_dict) { - return {}; - } - - const std::string* const type = payload_dict->FindString(kTypeParameterName); - if (!type || *type != kTypeViewParameterValue) { - return {}; - } - - const std::string* const creative_instance_id = - payload_dict->FindString(kCreativeInstanceIdParameterName); - if (!creative_instance_id) { - return {}; - } - - return *creative_instance_id; -} - -} // namespace brave_ads diff --git a/components/brave_ads/common/search_result_ad_util.h b/components/brave_ads/common/search_result_ad_util.h deleted file mode 100644 index 03afb3ecb59d..000000000000 --- a/components/brave_ads/common/search_result_ad_util.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2022 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_COMMON_SEARCH_RESULT_AD_UTIL_H_ -#define BRAVE_COMPONENTS_BRAVE_ADS_COMMON_SEARCH_RESULT_AD_UTIL_H_ - -#include - -class GURL; - -namespace network { -struct ResourceRequest; -} // namespace network - -namespace brave_ads { - -bool IsSearchResultAdViewedConfirmationUrl(const GURL& url); - -std::string GetViewedSearchResultAdCreativeInstanceId( - const network::ResourceRequest& request); - -} // namespace brave_ads - -#endif // BRAVE_COMPONENTS_BRAVE_ADS_COMMON_SEARCH_RESULT_AD_UTIL_H_ diff --git a/components/brave_ads/common/search_result_ad_util_unittest.cc b/components/brave_ads/common/search_result_ad_util_unittest.cc deleted file mode 100644 index 83350f0f802d..000000000000 --- a/components/brave_ads/common/search_result_ad_util_unittest.cc +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (c) 2022 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/common/search_result_ad_util.h" -#include "base/strings/string_piece.h" -#include "services/network/public/cpp/resource_request.h" -#include "testing/gtest/include/gtest/gtest.h" // IWYU pragma: keep -#include "url/gurl.h" - -namespace brave_ads { - -TEST(SearchResultAdUtilTest, CheckSearchResultAdViewedConfirmationUrl) { - EXPECT_TRUE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.brave.com/v3/confirmation"))); - EXPECT_TRUE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.bravesoftware.com/v3/confirmation"))); - - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("http://search.anonymous.brave.com/v3/confirmation"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("http://search.anonymous.bravesoftware.com/v3/confirmation"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.brave.com/v4/confirmation"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.bravesoftware.com/v4/confirmation"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.brave.com/v3/non"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.bravesoftware.com/v3/non"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.brave.com/v3/confirmation"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.bravesoftware.com/v3/confirmation"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.brave.com/v3"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.bravesoftware.com/v3"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.brave.com"))); - EXPECT_FALSE(IsSearchResultAdViewedConfirmationUrl( - GURL("https://search.anonymous.bravesoftware.com"))); -} - -TEST(SearchResultAdUtilTest, CheckGetViewedSearchResultAdCreativeInstanceId) { - network::ResourceRequest request; - request.method = "POST"; - request.url = GURL("https://search.anonymous.brave.com/v3/confirmation"); - base::StringPiece json_payload = R"({ - "type": "view", - "creativeInstanceId": "creative-instance-id" - })"; - request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_EQ("creative-instance-id", - GetViewedSearchResultAdCreativeInstanceId(request)); - - network::ResourceRequest bad_request = request; - bad_request.method = "GET"; - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - bad_request.url = GURL("https://search.brave.com/v3/confirmation"); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - bad_request.request_body.reset(); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - json_payload = ""; - bad_request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - json_payload = "abc"; - bad_request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - json_payload = R"({ - "type": "view" - "creativeInstanceId": "creative-instance-id" - })"; - bad_request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - json_payload = R"([{ - "type": "view", - "creativeInstanceId": "creative-instance-id" - }])"; - bad_request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - json_payload = R"({ - "no-type": "view", - "creativeInstanceId": "creative-instance-id" - })"; - bad_request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - json_payload = R"({ - "not-type": "view", - "creativeInstanceId": "creative-instance-id" - })"; - bad_request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); - - bad_request = request; - json_payload = R"({ - "type": "click", - "not-creativeInstanceId": "creative-instance-id" - })"; - bad_request.request_body = network::ResourceRequestBody::CreateFromBytes( - json_payload.data(), json_payload.size()); - EXPECT_TRUE(GetViewedSearchResultAdCreativeInstanceId(bad_request).empty()); -} - -} // namespace brave_ads diff --git a/components/brave_ads/content/browser/search_result_ad/BUILD.gn b/components/brave_ads/content/browser/search_result_ad/BUILD.gn index 1bb9f346e5d2..1a1dc29f5726 100644 --- a/components/brave_ads/content/browser/search_result_ad/BUILD.gn +++ b/components/brave_ads/content/browser/search_result_ad/BUILD.gn @@ -5,23 +5,22 @@ source_set("search_result_ad") { sources = [ - "search_result_ad_parsing.cc", - "search_result_ad_parsing.h", - "search_result_ad_service.cc", - "search_result_ad_service.h", + "search_result_ad_handler.cc", + "search_result_ad_handler.h", ] deps = [ "//base", "//brave/components/brave_ads/browser", "//brave/components/brave_ads/common", + "//brave/components/brave_ads/core/browser/search_result_ad", "//brave/components/brave_search/common", "//components/schema_org/common:mojom", - "//components/sessions", "//content/public/browser", "//mojo/public/cpp/bindings", "//services/service_manager/public/cpp", "//third_party/abseil-cpp:absl", + "//third_party/blink/public/common", ] public_deps = [ diff --git a/components/brave_ads/content/browser/search_result_ad/DEPS b/components/brave_ads/content/browser/search_result_ad/DEPS index fbe6fcd84a4b..546a152e2a9e 100644 --- a/components/brave_ads/content/browser/search_result_ad/DEPS +++ b/components/brave_ads/content/browser/search_result_ad/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+content/public/browser", + "+services/network/public/cpp", "+services/service_manager/public/cpp", - "+third_party/blink/public/mojom/document_metadata", + "+third_party/blink/public", ] diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc new file mode 100644 index 000000000000..e5c62098453d --- /dev/null +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc @@ -0,0 +1,112 @@ +/* Copyright (c) 2022 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/content/browser/search_result_ad/search_result_ad_handler.h" + +#include + +#include "base/memory/ptr_util.h" +#include "brave/components/brave_ads/browser/ads_service.h" +#include "brave/components/brave_ads/common/features.h" +#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h" +#include "brave/components/brave_search/common/brave_search_utils.h" +#include "content/public/browser/render_frame_host.h" +#include "services/service_manager/public/cpp/interface_provider.h" + +namespace brave_ads { + +SearchResultAdHandler::SearchResultAdHandler(AdsService* ads_service, + bool should_trigger_viewed_event) + : ads_service_(ads_service), + should_trigger_viewed_event_(should_trigger_viewed_event) { + DCHECK(ads_service_); +} + +SearchResultAdHandler::~SearchResultAdHandler() = default; + +// static +std::unique_ptr +SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + AdsService* ads_service, + const GURL& url, + bool should_trigger_viewed_event) { + if (!ads_service || !ads_service->IsEnabled() || + !base::FeatureList::IsEnabled( + features::kSupportBraveSearchResultAdConfirmationEvents) || + !brave_search::IsAllowedHost(url)) { + return {}; + } + + return base::WrapUnique( + new SearchResultAdHandler(ads_service, should_trigger_viewed_event)); +} + +void SearchResultAdHandler::MaybeRetrieveSearchResultAd( + content::RenderFrameHost* render_frame_host) { + DCHECK(render_frame_host); + DCHECK(ads_service_); + + if (!ads_service_->IsEnabled()) { + return; + } + + mojo::Remote document_metadata; + render_frame_host->GetRemoteInterfaces()->GetInterface( + document_metadata.BindNewPipeAndPassReceiver()); + DCHECK(document_metadata.is_bound()); + document_metadata.reset_on_disconnect(); + + blink::mojom::DocumentMetadata* raw_document_metadata = + document_metadata.get(); + raw_document_metadata->GetEntities( + base::BindOnce(&SearchResultAdHandler::OnRetrieveSearchResultAdEntities, + weak_factory_.GetWeakPtr(), std::move(document_metadata))); +} + +void SearchResultAdHandler::MaybeTriggerSearchResultAdClickedEvent( + const GURL& navigation_url) { + DCHECK(navigation_url.is_valid()); + DCHECK(ads_service_); + + if (!ads_service_->IsEnabled() || !search_result_ads_) { + return; + } + + auto it = search_result_ads_->find(navigation_url); + if (it == search_result_ads_->end()) { + return; + } + + const ads::mojom::SearchResultAdInfoPtr& search_result_ad = it->second; + DCHECK(search_result_ad); + DCHECK(search_result_ad->target_url.is_valid() && + search_result_ad->target_url.SchemeIs(url::kHttpsScheme)); + + ads_service_->TriggerSearchResultAdEvent( + search_result_ad->Clone(), ads::mojom::SearchResultAdEventType::kClicked); +} + +void SearchResultAdHandler::OnRetrieveSearchResultAdEntities( + mojo::Remote /*document_metadata*/, + blink::mojom::WebPagePtr web_page) { + DCHECK(ads_service_); + + if (!ads_service_->IsEnabled() || !web_page) { + return; + } + + search_result_ads_ = ParseWebPageEntities(std::move(web_page)); + + if (search_result_ads_ && should_trigger_viewed_event_) { + for (const auto& [key, search_result_ad] : *search_result_ads_) { + DCHECK(search_result_ad); + ads_service_->TriggerSearchResultAdEvent( + search_result_ad->Clone(), + ads::mojom::SearchResultAdEventType::kViewed); + } + } +} + +} // namespace brave_ads diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h new file mode 100644 index 000000000000..5880d681f86e --- /dev/null +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2022 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_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_HANDLER_H_ +#define BRAVE_COMPONENTS_BRAVE_ADS_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_HANDLER_H_ + +#include +#include + +#include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" +#include "url/gurl.h" + +namespace content { +class RenderFrameHost; +} + +namespace brave_ads { + +class AdsService; + +class SearchResultAdHandler final { + public: + ~SearchResultAdHandler(); + + SearchResultAdHandler(const SearchResultAdHandler&) = delete; + SearchResultAdHandler& operator=(const SearchResultAdHandler&) = delete; + SearchResultAdHandler(SearchResultAdHandler&&) noexcept = delete; + SearchResultAdHandler& operator=(SearchResultAdHandler&&) noexcept = delete; + + static std::unique_ptr + MaybeCreateSearchResultAdHandler(AdsService* ads_service, + const GURL& url, + bool should_trigger_viewed_event); + + void MaybeRetrieveSearchResultAd(content::RenderFrameHost* render_frame_host); + + void MaybeTriggerSearchResultAdClickedEvent(const GURL& navigation_url); + + private: + friend class SearchResultAdHandlerTest; + + SearchResultAdHandler(AdsService* ads_service, + bool should_trigger_viewed_event); + + void OnRetrieveSearchResultAdEntities( + mojo::Remote document_metadata, + blink::mojom::WebPagePtr web_page); + + raw_ptr ads_service_ = nullptr; // NOT OWNED + bool should_trigger_viewed_event_ = true; + + absl::optional> + search_result_ads_; + + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace brave_ads + +#endif // BRAVE_COMPONENTS_BRAVE_ADS_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_HANDLER_H_ diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc new file mode 100644 index 000000000000..4e355535217e --- /dev/null +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc @@ -0,0 +1,187 @@ +/* Copyright (c) 2022 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 +#include + +#include "base/test/scoped_feature_list.h" +#include "brave/components/brave_ads/browser/mock_ads_service.h" +#include "brave/components/brave_ads/common/features.h" +#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h" +#include "brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace brave_ads { +namespace { + +using testing::_; +using testing::Mock; +using testing::Return; + +constexpr char kAllowedDomain[] = "https://search.brave.com"; +constexpr char kNotAllowedDomain[] = "https://brave.com"; + +} // namespace + +class SearchResultAdHandlerTest : public ::testing::Test { + public: + SearchResultAdHandlerTest() { + feature_list_.InitAndEnableFeature( + features::kSupportBraveSearchResultAdConfirmationEvents); + } + ~SearchResultAdHandlerTest() override = default; + + SearchResultAdHandlerTest(const SearchResultAdHandlerTest&) = delete; + SearchResultAdHandlerTest& operator=(const SearchResultAdHandlerTest&) = + delete; + + static void SimulateOnRetrieveSearchResultAdEntities( + SearchResultAdHandler* search_result_ad_handler, + blink::mojom::WebPagePtr web_page) { + search_result_ad_handler->OnRetrieveSearchResultAdEntities( + mojo::Remote(), std::move(web_page)); + } + + protected: + MockAdsService ads_service_; + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(SearchResultAdHandlerTest, + BraveAdsDisabledMaybeCreateSearchResultAdHandler) { + EXPECT_CALL(ads_service_, IsEnabled()).WillOnce(Return(false)); + + auto search_result_ad_handler = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + &ads_service_, GURL(kAllowedDomain), + /*should_trigger_viewed_event*/ true); + + EXPECT_FALSE(search_result_ad_handler.get()); +} + +TEST_F(SearchResultAdHandlerTest, + IncognitoModeMaybeCreateSearchResultAdHandler) { + auto search_result_ad_handler = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + nullptr, GURL(kAllowedDomain), /*should_trigger_viewed_event*/ true); + + EXPECT_FALSE(search_result_ad_handler.get()); +} + +TEST_F(SearchResultAdHandlerTest, + NotAllowedDomainMaybeCreateSearchResultAdHandler) { + EXPECT_CALL(ads_service_, IsEnabled()).WillOnce(Return(true)); + + auto search_result_ad_handler = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + &ads_service_, GURL(kNotAllowedDomain), + /*should_trigger_viewed_event*/ true); + + EXPECT_FALSE(search_result_ad_handler.get()); +} + +TEST_F(SearchResultAdHandlerTest, BraveAdsEmpty) { + EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kViewed)) + .Times(0); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kClicked)) + .Times(0); + + auto search_result_ad_handler = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + &ads_service_, GURL(kAllowedDomain), + /*should_trigger_viewed_event*/ true); + ASSERT_TRUE(search_result_ad_handler.get()); + + SimulateOnRetrieveSearchResultAdEntities(search_result_ad_handler.get(), + blink::mojom::WebPage::New()); + + search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( + GURL(kTargetUrl)); +} + +TEST_F(SearchResultAdHandlerTest, BraveAdsBecomeDisabled) { + EXPECT_CALL(ads_service_, IsEnabled()).WillOnce(Return(true)); + + auto search_result_ad_handler = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + &ads_service_, GURL(kAllowedDomain), + /*should_trigger_viewed_event*/ true); + ASSERT_TRUE(search_result_ad_handler.get()); + Mock::VerifyAndClearExpectations(&ads_service_); + + EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(false)); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kViewed)) + .Times(0); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kClicked)) + .Times(0); + + SimulateOnRetrieveSearchResultAdEntities(search_result_ad_handler.get(), + CreateTestWebPage()); + + search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( + GURL(kTargetUrl)); +} + +TEST_F(SearchResultAdHandlerTest, BraveAdsViewedClicked) { + EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kViewed)); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kClicked)) + .Times(2); + + auto search_result_ad_handler = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + &ads_service_, GURL(kAllowedDomain), + /*should_trigger_viewed_event*/ true); + ASSERT_TRUE(search_result_ad_handler.get()); + + SimulateOnRetrieveSearchResultAdEntities(search_result_ad_handler.get(), + CreateTestWebPage()); + + search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( + GURL(kTargetUrl)); + + search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( + GURL(kTargetUrl)); +} + +TEST_F(SearchResultAdHandlerTest, BraveAdsTabRestored) { + EXPECT_CALL(ads_service_, IsEnabled()).WillRepeatedly(Return(true)); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kViewed)) + .Times(0); + EXPECT_CALL(ads_service_, + TriggerSearchResultAdEvent( + _, ads::mojom::SearchResultAdEventType::kClicked)); + + auto search_result_ad_handler = + SearchResultAdHandler::MaybeCreateSearchResultAdHandler( + &ads_service_, GURL(kAllowedDomain), + /*should_trigger_viewed_event*/ false); + ASSERT_TRUE(search_result_ad_handler.get()); + + SimulateOnRetrieveSearchResultAdEntities(search_result_ad_handler.get(), + CreateTestWebPage()); + + search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( + GURL(kTargetUrl)); +} + +} // namespace brave_ads diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing_unittest.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing_unittest.cc deleted file mode 100644 index e538508fd2f1..000000000000 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing_unittest.cc +++ /dev/null @@ -1,305 +0,0 @@ -/* Copyright (c) 2022 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 -#include -#include - -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.h" -#include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" // IWYU pragma: keep -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" - -namespace brave_ads { - -namespace { - -schema_org::mojom::ValuesPtr CreateVectorValuesPtr(std::string value) { - return schema_org::mojom::Values::NewStringValues({std::move(value)}); -} - -schema_org::mojom::ValuesPtr CreateVectorValuesPtr(int64_t value) { - return schema_org::mojom::Values::NewLongValues({value}); -} - -class TestWebPageConstructor final { - public: - explicit TestWebPageConstructor(int attribute_index_to_skip = -1) - : attribute_index_to_skip_(attribute_index_to_skip) { - web_page_ = CreateWebPage(); - } - ~TestWebPageConstructor() = default; - TestWebPageConstructor(const TestWebPageConstructor&) = delete; - TestWebPageConstructor& operator=(const TestWebPageConstructor&) = delete; - - blink::mojom::WebPagePtr GetWebPage() { return std::move(web_page_); } - - private: - blink::mojom::WebPagePtr CreateWebPage() { - blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); - schema_org::mojom::EntityPtr entity = schema_org::mojom::Entity::New(); - entity->type = "Product"; - schema_org::mojom::PropertyPtr property = - schema_org::mojom::Property::New(); - property->name = "creatives"; - - std::vector entity_values; - entity_values.push_back(CreateCreativeEntity()); - property->values = - schema_org::mojom::Values::NewEntityValues(std::move(entity_values)); - - entity->properties.push_back(std::move(property)); - web_page->entities.push_back(std::move(entity)); - - return web_page; - } - - template - void AddProperty(std::vector* properties, - base::StringPiece name, - T value) { - const int index = current_attribute_index_++; - if (index == attribute_index_to_skip_) { - return; - } - schema_org::mojom::PropertyPtr property = - schema_org::mojom::Property::New(); - property->name = static_cast(name); - property->values = CreateVectorValuesPtr(value); - - properties->push_back(std::move(property)); - } - - schema_org::mojom::EntityPtr CreateCreativeEntity() { - static constexpr const char* kSearchResultAdStringAttributes[] = { - "data-creative-instance-id", - "data-placement-id", - "data-creative-set-id", - "data-campaign-id", - "data-advertiser-id", - "data-headline-text", - "data-description", - "data-conversion-type-value", - "data-conversion-url-pattern-value", - "data-conversion-advertiser-public-key-value"}; - - schema_org::mojom::EntityPtr entity = schema_org::mojom::Entity::New(); - entity->type = "SearchResultAd"; - - AddProperty(&entity->properties, "data-landing-page", - "https://target.url"); - AddProperty(&entity->properties, "data-rewards-value", "0.5"); - AddProperty(&entity->properties, - "data-conversion-observation-window-value", 1); - - int index = 0; - for (const auto* const* iter = std::begin(kSearchResultAdStringAttributes); - iter != std::end(kSearchResultAdStringAttributes); ++iter, ++index) { - AddProperty( - &entity->properties, *iter, - std::string("value") + base::NumberToString(index)); - } - - return entity; - } - - blink::mojom::WebPagePtr web_page_; - int current_attribute_index_ = 0; - int attribute_index_to_skip_ = -1; -}; - -TEST(SearchResultAdParsingTest, ValidWebPage) { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_EQ(ads.size(), 1U); - ads::mojom::SearchResultAdInfoPtr& search_result_ad = ads["value0"]; - ASSERT_TRUE(search_result_ad.get()); - - EXPECT_EQ(search_result_ad->target_url, GURL("https://target.url")); - EXPECT_EQ(search_result_ad->value, 0.5); - EXPECT_EQ( - static_cast(search_result_ad->conversion->observation_window), - 1U); - - EXPECT_EQ(search_result_ad->creative_instance_id, "value0"); - EXPECT_EQ(search_result_ad->placement_id, "value1"); - EXPECT_EQ(search_result_ad->creative_set_id, "value2"); - EXPECT_EQ(search_result_ad->campaign_id, "value3"); - EXPECT_EQ(search_result_ad->advertiser_id, "value4"); - EXPECT_EQ(search_result_ad->headline_text, "value5"); - EXPECT_EQ(search_result_ad->description, "value6"); - EXPECT_EQ(search_result_ad->conversion->type, "value7"); - EXPECT_EQ(search_result_ad->conversion->url_pattern, "value8"); - EXPECT_EQ(search_result_ad->conversion->advertiser_public_key, "value9"); -} - -TEST(SearchResultAdParsingTest, NotValidWebPage) { - { - blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - web_page->entities[0]->type = "Not-Product"; - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - web_page->entities[0]->properties.clear(); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - property->name = "not-creatives"; - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - property->values = schema_org::mojom::Values::NewEntityValues({}); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - property->values = schema_org::mojom::Values::NewStringValues({"creative"}); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } -} - -TEST(SearchResultAdParsingTest, NotValidAdEntityExtraProperty) { - { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - auto& ad_entity = property->values->get_entity_values()[0]; - ad_entity->type = "Not-SearchResultAd"; - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - TestWebPageConstructor constructor; - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - auto& ad_entity = property->values->get_entity_values()[0]; - - schema_org::mojom::PropertyPtr extra_property = - schema_org::mojom::Property::New(); - extra_property->name = "extra-name"; - extra_property->values = - schema_org::mojom::Values::NewStringValues({"extra-value"}); - ad_entity->properties.push_back(std::move(extra_property)); - - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } -} - -TEST(SearchResultAdParsingTest, NotValidAdEntityPropertySkipped) { - constexpr int kSearchResultAdAttributesCount = 12; - for (int index = 0; index < kSearchResultAdAttributesCount; ++index) { - TestWebPageConstructor constructor(index); - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } -} - -TEST(SearchResultAdParsingTest, NotValidAdEntityWrongPropertyType) { - { - // Skip "data-landing-page". - TestWebPageConstructor constructor(0); - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - auto& ad_entity = property->values->get_entity_values()[0]; - - schema_org::mojom::PropertyPtr extra_property = - schema_org::mojom::Property::New(); - extra_property->name = "data-landing-page"; - extra_property->values = - schema_org::mojom::Values::NewStringValues({"http://target.url"}); - ad_entity->properties.push_back(std::move(extra_property)); - - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - // Skip "data-rewards-value". - TestWebPageConstructor constructor(1); - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - auto& ad_entity = property->values->get_entity_values()[0]; - - schema_org::mojom::PropertyPtr extra_property = - schema_org::mojom::Property::New(); - extra_property->name = "data-rewards-value"; - extra_property->values = - schema_org::mojom::Values::NewStringValues({"0-5"}); - ad_entity->properties.push_back(std::move(extra_property)); - - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - // Skip "data-conversion-observation-window-value". - TestWebPageConstructor constructor(2); - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - auto& ad_entity = property->values->get_entity_values()[0]; - - schema_org::mojom::PropertyPtr extra_property = - schema_org::mojom::Property::New(); - extra_property->name = "data-conversion-observation-window-value"; - extra_property->values = schema_org::mojom::Values::NewStringValues({"1"}); - ad_entity->properties.push_back(std::move(extra_property)); - - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } - - { - // Skip "data-creative-instance-id". - TestWebPageConstructor constructor(3); - blink::mojom::WebPagePtr web_page = constructor.GetWebPage(); - auto& property = web_page->entities[0]->properties[0]; - auto& ad_entity = property->values->get_entity_values()[0]; - - schema_org::mojom::PropertyPtr extra_property = - schema_org::mojom::Property::New(); - extra_property->name = "data-creative-instance-id"; - extra_property->values = schema_org::mojom::Values::NewLongValues({101}); - ad_entity->properties.push_back(std::move(extra_property)); - - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); - EXPECT_TRUE(ads.empty()); - } -} - -} // namespace - -} // namespace brave_ads diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.cc deleted file mode 100644 index d116cb446c31..000000000000 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* Copyright (c) 2022 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/content/browser/search_result_ad/search_result_ad_service.h" - -#include - -#include "base/check.h" -#include "base/containers/contains.h" -#include "base/feature_list.h" // IWYU pragma: keep -#include "base/functional/callback.h" -#include "brave/components/brave_ads/browser/ads_service.h" -#include "brave/components/brave_ads/common/features.h" -#include "brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.h" -#include "brave/components/brave_search/common/brave_search_utils.h" -#include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom-shared.h" -#include "content/public/browser/render_frame_host.h" // IWYU pragma: keep -#include "services/service_manager/public/cpp/interface_provider.h" -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" - -namespace brave_ads { - -SearchResultAdService::AdViewedEventCallbackInfo::AdViewedEventCallbackInfo() = - default; -SearchResultAdService::AdViewedEventCallbackInfo::AdViewedEventCallbackInfo( - AdViewedEventCallbackInfo&& info) noexcept = default; -SearchResultAdService::AdViewedEventCallbackInfo& -SearchResultAdService::AdViewedEventCallbackInfo::operator=( - AdViewedEventCallbackInfo&& info) noexcept = default; -SearchResultAdService::AdViewedEventCallbackInfo::~AdViewedEventCallbackInfo() = - default; - -SearchResultAdService::SearchResultAdService(AdsService* ads_service) - : ads_service_(ads_service) { - DCHECK(ads_service_); -} - -SearchResultAdService::~SearchResultAdService() = default; - -void SearchResultAdService::MaybeRetrieveSearchResultAd( - content::RenderFrameHost* render_frame_host, - SessionID tab_id, - bool should_trigger_viewed_event) { - DCHECK(ads_service_); - DCHECK(render_frame_host); - DCHECK(tab_id.is_valid()); - - if (!should_trigger_viewed_event || !ads_service_->IsEnabled() || - !base::FeatureList::IsEnabled( - features::kSupportBraveSearchResultAdConfirmationEvents) || - !brave_search::IsAllowedHost(render_frame_host->GetLastCommittedURL())) { - if (metadata_request_finished_callback_for_testing_) { - std::move(metadata_request_finished_callback_for_testing_).Run(); - } - search_result_ads_[tab_id] = SearchResultAdMap(); - RunAdViewedEventPendingCallbacks(tab_id, /*ads_fetched*/ false); - return; - } - - mojo::Remote document_metadata; - render_frame_host->GetRemoteInterfaces()->GetInterface( - document_metadata.BindNewPipeAndPassReceiver()); - DCHECK(document_metadata.is_bound()); - document_metadata.reset_on_disconnect(); - - blink::mojom::DocumentMetadata* raw_document_metadata = - document_metadata.get(); - raw_document_metadata->GetEntities(base::BindOnce( - &SearchResultAdService::OnRetrieveSearchResultAdEntities, - weak_factory_.GetWeakPtr(), std::move(document_metadata), tab_id)); -} - -void SearchResultAdService::OnDidFinishNavigation(SessionID tab_id) { - // Clear the tab state from the previous load. - ResetState(tab_id); - // Now ad viewed events callbacks will be cached before search result JSON-ld - // is loaded and processed. - ad_viewed_event_pending_callbacks_[tab_id] = - std::vector(); -} - -void SearchResultAdService::OnDidCloseTab(SessionID tab_id) { - // Clear the tab state in memory. - ResetState(tab_id); -} - -void SearchResultAdService::MaybeTriggerSearchResultAdViewedEvent( - const std::string& creative_instance_id, - SessionID tab_id, - base::OnceCallback callback) { - DCHECK(ads_service_); - DCHECK(!creative_instance_id.empty()); - DCHECK(tab_id.is_valid()); - - if (!ads_service_->IsEnabled()) { - std::move(callback).Run(/*event_triggered*/ false); - return; - } - - // Check if search result ad JSON-LD wasn't processed yet. - if (!base::Contains(search_result_ads_, tab_id)) { - // Check if OnDidFinishNavigation was called for tab_id. - if (!base::Contains(ad_viewed_event_pending_callbacks_, tab_id)) { - std::move(callback).Run(/*event_triggered*/ false); - return; - } - - AdViewedEventCallbackInfo callback_info; - callback_info.creative_instance_id = creative_instance_id; - callback_info.callback = std::move(callback); - ad_viewed_event_pending_callbacks_[tab_id].push_back( - std::move(callback_info)); - return; - } - - const bool event_triggered = - TriggerSearchResultAdViewedEvent(creative_instance_id, tab_id); - std::move(callback).Run(event_triggered); -} - -void SearchResultAdService::SetMetadataRequestFinishedCallbackForTesting( - base::OnceClosure callback) { - metadata_request_finished_callback_for_testing_ = std::move(callback); -} - -AdsService* SearchResultAdService::SetAdsServiceForTesting( - AdsService* ads_service) { - AdsService* const previous_ads_service = ads_service_.get(); - ads_service_ = ads_service; - return previous_ads_service; -} - -void SearchResultAdService::ResetState(SessionID tab_id) { - DCHECK(tab_id.is_valid()); - - for (auto& callback_info : ad_viewed_event_pending_callbacks_[tab_id]) { - std::move(callback_info.callback).Run(false); - } - ad_viewed_event_pending_callbacks_.erase(tab_id); - search_result_ads_.erase(tab_id); -} - -void SearchResultAdService::OnRetrieveSearchResultAdEntities( - mojo::Remote /*document_metadata*/, - SessionID tab_id, - blink::mojom::WebPagePtr web_page) { - if (metadata_request_finished_callback_for_testing_) { - std::move(metadata_request_finished_callback_for_testing_).Run(); - } - - if (!web_page) { - search_result_ads_[tab_id] = SearchResultAdMap(); - RunAdViewedEventPendingCallbacks(tab_id, /*ads_fetched*/ false); - return; - } - - SearchResultAdMap search_result_ads = - ParseWebPageEntities(std::move(web_page)); - - search_result_ads_.emplace(tab_id, std::move(search_result_ads)); - - RunAdViewedEventPendingCallbacks(tab_id, /*ads_fetched*/ true); -} - -void SearchResultAdService::RunAdViewedEventPendingCallbacks(SessionID tab_id, - bool ads_fetched) { - for (auto& callback_info : ad_viewed_event_pending_callbacks_[tab_id]) { - bool event_triggered = false; - if (ads_fetched) { - event_triggered = TriggerSearchResultAdViewedEvent( - callback_info.creative_instance_id, tab_id); - } - if (event_triggered) { - VLOG(1) << "Triggered search result ad viewed event for " - << callback_info.creative_instance_id; - } else { - VLOG(1) << "Failed to trigger search result ad viewed event for " - << callback_info.creative_instance_id; - } - std::move(callback_info.callback).Run(event_triggered); - } - ad_viewed_event_pending_callbacks_.erase(tab_id); -} - -bool SearchResultAdService::TriggerSearchResultAdViewedEvent( - const std::string& creative_instance_id, - SessionID tab_id) { - DCHECK(!creative_instance_id.empty()); - DCHECK(tab_id.is_valid()); - DCHECK(ads_service_); - - SearchResultAdMap& ad_map = search_result_ads_[tab_id]; - auto it = ad_map.find(creative_instance_id); - if (it == ad_map.end()) { - return false; - } - - ads::mojom::SearchResultAdInfoPtr ad_mojom = std::move(it->second); - ads_service_->TriggerSearchResultAdEvent( - std::move(ad_mojom), ads::mojom::SearchResultAdEventType::kViewed); - ad_map.erase(creative_instance_id); - - return true; -} - -} // namespace brave_ads diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h b/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h deleted file mode 100644 index 09e6d490747f..000000000000 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_service.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (c) 2022 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_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_SERVICE_H_ -#define BRAVE_COMPONENTS_BRAVE_ADS_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_SERVICE_H_ - -#include -#include -#include - -#include "base/functional/callback.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom-forward.h" -#include "components/keyed_service/core/keyed_service.h" -#include "components/sessions/core/session_id.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom-forward.h" - -namespace content { -class RenderFrameHost; -} // namespace content - -namespace brave_ads { - -class AdsService; - -// Retrieves search result ads from page and handles viewed/clicked events. -class SearchResultAdService : public KeyedService { - public: - explicit SearchResultAdService(AdsService* ads_service); - - SearchResultAdService(const SearchResultAdService&) = delete; - SearchResultAdService& operator=(const SearchResultAdService&) = delete; - - SearchResultAdService(SearchResultAdService&& other) noexcept = delete; - SearchResultAdService& operator=(SearchResultAdService&& other) noexcept = - delete; - - ~SearchResultAdService() override; - - // Retrieves search result ads from the render frame. - // If should_trigger_viewed_event value is false, then viewed - // events shouldn't be sent to the ads library. - void MaybeRetrieveSearchResultAd(content::RenderFrameHost* render_frame_host, - SessionID tab_id, - bool should_trigger_viewed_event); - - // Removes search result ads from the previous page load. - void OnDidFinishNavigation(SessionID tab_id); - - // Removes search result ads when closing the tab. - void OnDidCloseTab(SessionID tab_id); - - // Triggers a search result ad viewed event on a specific tab. - void MaybeTriggerSearchResultAdViewedEvent( - const std::string& creative_instance_id, - SessionID tab_id, - base::OnceCallback callback); - - void SetMetadataRequestFinishedCallbackForTesting(base::OnceClosure callback); - - AdsService* SetAdsServiceForTesting(AdsService* ads_service); - - private: - struct AdViewedEventCallbackInfo { - AdViewedEventCallbackInfo(); - AdViewedEventCallbackInfo(AdViewedEventCallbackInfo&& info) noexcept; - AdViewedEventCallbackInfo& operator=( - AdViewedEventCallbackInfo&& info) noexcept; - ~AdViewedEventCallbackInfo(); - - std::string creative_instance_id; - base::OnceCallback callback; - }; - - void ResetState(SessionID tab_id); - - void OnRetrieveSearchResultAdEntities( - mojo::Remote document_metadata, - SessionID tab_id, - blink::mojom::WebPagePtr web_page); - - void RunAdViewedEventPendingCallbacks(SessionID tab_id, bool ads_fetched); - - bool TriggerSearchResultAdViewedEvent(const std::string& creative_instance_id, - SessionID tab_id); - - raw_ptr ads_service_ = nullptr; - - std::map> - search_result_ads_; - - std::map> - ad_viewed_event_pending_callbacks_; - - base::OnceClosure metadata_request_finished_callback_for_testing_; - - base::WeakPtrFactory weak_factory_{this}; -}; - -} // namespace brave_ads - -#endif // BRAVE_COMPONENTS_BRAVE_ADS_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_SERVICE_H_ diff --git a/components/brave_ads/core/browser/search_result_ad/BUILD.gn b/components/brave_ads/core/browser/search_result_ad/BUILD.gn new file mode 100644 index 000000000000..edb612a00b57 --- /dev/null +++ b/components/brave_ads/core/browser/search_result_ad/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2022 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/. + +source_set("search_result_ad") { + sources = [ + "search_result_ad_parsing.cc", + "search_result_ad_parsing.h", + ] + + deps = [ + "//base", + "//components/schema_org/common:mojom", + "//services/network/public/cpp", + "//third_party/abseil-cpp:absl", + "//url", + ] + + public_deps = [ + "//brave/vendor/bat-native-ads", + "//third_party/blink/public/mojom:mojom_platform_headers", + ] +} diff --git a/components/brave_ads/core/browser/search_result_ad/DEPS b/components/brave_ads/core/browser/search_result_ad/DEPS new file mode 100644 index 000000000000..7739ebf24138 --- /dev/null +++ b/components/brave_ads/core/browser/search_result_ad/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "+services/network/public/cpp", + "+third_party/blink/public", +] diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.cc similarity index 62% rename from components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.cc rename to components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.cc index c233e7def975..4897113a325c 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.cc +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.cc @@ -3,9 +3,9 @@ * 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/content/browser/search_result_ad/search_result_ad_parsing.h" +#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h" -#include +#include #include #include @@ -14,7 +14,7 @@ #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom.h" -#include "third_party/abseil-cpp/absl/types/optional.h" +#include "components/schema_org/common/metadata.mojom.h" #include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" using ads::mojom::ConversionInfo; @@ -29,8 +29,7 @@ namespace { constexpr char kProductType[] = "Product"; constexpr char kSearchResultAdType[] = "SearchResultAd"; -constexpr char kContextPropertyName[] = "@context"; -constexpr char kTypePropertyName[] = "@type"; +constexpr char kCreativesPropertyName[] = "creatives"; constexpr char kDataPlacementId[] = "data-placement-id"; constexpr char kDataCreativeInstanceId[] = "data-creative-instance-id"; @@ -63,7 +62,7 @@ bool GetStringValue(const schema_org::mojom::PropertyPtr& ad_property, DCHECK(ad_property); DCHECK(out_value); - // Wrong attribute type + // Wrong attribute type. if (!ad_property->values->is_string_values() || ad_property->values->get_string_values().size() != 1) { return false; @@ -79,7 +78,7 @@ bool GetIntValue(const schema_org::mojom::PropertyPtr& ad_property, DCHECK(ad_property); DCHECK(out_value); - // Wrong attribute type + // Wrong attribute type. if (!ad_property->values->is_long_values() || ad_property->values->get_long_values().size() != 1) { return false; @@ -96,7 +95,7 @@ bool GetDoubleValue(const schema_org::mojom::PropertyPtr& ad_property, DCHECK(ad_property); DCHECK(out_value); - // Wrong attribute type + // Wrong attribute type. if (!ad_property->values->is_string_values() || ad_property->values->get_string_values().size() != 1) { return false; @@ -111,7 +110,7 @@ bool GetUrlValue(const schema_org::mojom::PropertyPtr& ad_property, DCHECK(ad_property); DCHECK(out_value); - // Wrong attribute type + // Wrong attribute type. if (!ad_property->values->is_string_values() || ad_property->values->get_string_values().size() != 1) { return false; @@ -194,130 +193,111 @@ bool SetSearchAdProperty(const schema_org::mojom::PropertyPtr& ad_property, return false; } -// TODO(https://github.com/brave/brave-browser/issues/25971): Reduce cognitive -// complexity. -absl::optional ParseSearchResultAdMapEntityProperties( - const schema_org::mojom::EntityPtr& entity) { - DCHECK(entity); - DCHECK_EQ(entity->type, kProductType); +void ParseSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, + SearchResultAdMap* search_result_ads) { + DCHECK(search_result_ads); - SearchResultAdMap search_result_ads; + // Wrong search result ad type specified. + if (!ad_entity || ad_entity->type != kSearchResultAdType) { + return; + } - for (const auto& property : entity->properties) { - if (!property || property->name == kContextPropertyName || - property->name == kTypePropertyName) { - continue; - } + SearchResultAdInfoPtr search_result_ad = SearchResultAdInfo::New(); + search_result_ad->conversion = ConversionInfo::New(); - // Search result ads list product could have only "@context" and "creatives" - // properties. - if (property->name != "creatives") { - return absl::nullopt; + base::flat_set found_attributes; + for (const auto& ad_property : ad_entity->properties) { + if (!ad_property) { + return; } - if (!property->values->is_entity_values() || - property->values->get_entity_values().empty()) { - LOG(ERROR) << "Search result ad attributes list is empty"; - return SearchResultAdMap(); + const auto* it = base::ranges::find(kSearchResultAdAttributes, + base::StringPiece(ad_property->name)); + + // Unknown search result ad attribute specified. + if (it == kSearchResultAdAttributes.end()) { + continue; } + found_attributes.insert(*it); - for (const auto& ad_entity : property->values->get_entity_values()) { - if (!ad_entity || ad_entity->type != kSearchResultAdType) { - LOG(ERROR) << "Wrong search result ad type specified: " - << ad_entity->type; - return SearchResultAdMap(); - } - - if (property->name == kTypePropertyName) { - continue; - } - - SearchResultAdInfoPtr search_result_ad = SearchResultAdInfo::New(); - search_result_ad->conversion = ConversionInfo::New(); - - base::flat_set found_attributes; - for (const auto& ad_property : ad_entity->properties) { - // Wrong attribute name - const auto* it = base::ranges::find( - kSearchResultAdAttributes, base::StringPiece(ad_property->name)); - - if (it == kSearchResultAdAttributes.end()) { - LOG(ERROR) << "Wrong search result ad attribute specified: " - << ad_property->name; - return SearchResultAdMap(); - } - found_attributes.insert(*it); - - if (!SetSearchAdProperty(ad_property, search_result_ad.get())) { - LOG(ERROR) << "Cannot read search result ad attribute value: " - << ad_property->name; - return SearchResultAdMap(); - } - } - - // Not all of attributes were specified. - if (found_attributes.size() != kSearchResultAdAttributes.size()) { - std::vector absent_attributes; - base::ranges::set_difference(kSearchResultAdAttributes, - found_attributes, - std::back_inserter(absent_attributes)); - - LOG(ERROR) << "Some of search result ad attributes were not specified: " - << base::JoinString(absent_attributes, ", "); - - return SearchResultAdMap(); - } - - const std::string creative_instance_id = - search_result_ad->creative_instance_id; - search_result_ads.emplace(creative_instance_id, - std::move(search_result_ad)); + if (!SetSearchAdProperty(ad_property, search_result_ad.get())) { + VLOG(2) << "Cannot read search result ad attribute value: " + << ad_property->name; + return; } + } + + // Not all of attributes were specified. + if (found_attributes.size() != kSearchResultAdAttributes.size()) { + std::vector absent_attributes; + std::set_difference(kSearchResultAdAttributes.begin(), + kSearchResultAdAttributes.end(), + found_attributes.begin(), found_attributes.end(), + std::back_inserter(absent_attributes)); - // Creatives has been parsed. - break; + VLOG(2) << "Some of search result ad attributes were not specified: " + << base::JoinString(absent_attributes, ", "); + + return; } - return search_result_ads; + GURL target_url = search_result_ad->target_url; + search_result_ads->emplace(std::move(target_url), + std::move(search_result_ad)); +} + +void ParseWebPageEntityProperty(const schema_org::mojom::PropertyPtr& property, + SearchResultAdMap* search_result_ads) { + if (!property || property->name != kCreativesPropertyName) { + return; + } + + schema_org::mojom::ValuesPtr& values = property->values; + if (!values || !values->is_entity_values()) { + return; + } + + for (const auto& ad_entity : values->get_entity_values()) { + ParseSearchResultAdEntity(ad_entity, search_result_ads); + } } void LogSearchResultAdMap(const SearchResultAdMap& search_result_ads) { - if (!VLOG_IS_ON(1)) { + if (!VLOG_IS_ON(2)) { return; } if (search_result_ads.empty()) { - VLOG(1) << "Parsed search result ads list is empty."; return; } - VLOG(1) << "Parsed search result ads list:"; + VLOG(2) << "Parsed search result ads list:"; for (const auto& search_result_ad_pair : search_result_ads) { const auto& search_result_ad = search_result_ad_pair.second; - VLOG(1) << "Ad with \"" << kDataPlacementId + VLOG(2) << "Ad with \"" << kDataPlacementId << "\": " << search_result_ad->placement_id; - VLOG(1) << " \"" << kDataCreativeInstanceId + VLOG(2) << " \"" << kDataCreativeInstanceId << "\": " << search_result_ad->creative_instance_id; - VLOG(1) << " \"" << kDataCreativeSetId + VLOG(2) << " \"" << kDataCreativeSetId << "\": " << search_result_ad->creative_set_id; - VLOG(1) << " \"" << kDataCampaignId + VLOG(2) << " \"" << kDataCampaignId << "\": " << search_result_ad->campaign_id; - VLOG(1) << " \"" << kDataAdvertiserId + VLOG(2) << " \"" << kDataAdvertiserId << "\": " << search_result_ad->advertiser_id; - VLOG(1) << " \"" << kDataLandingPage + VLOG(2) << " \"" << kDataLandingPage << "\": " << search_result_ad->target_url; - VLOG(1) << " \"" << kDataHeadlineText + VLOG(2) << " \"" << kDataHeadlineText << "\": " << search_result_ad->headline_text; - VLOG(1) << " \"" << kDataDescription + VLOG(2) << " \"" << kDataDescription << "\": " << search_result_ad->description; - VLOG(1) << " \"" << kDataRewardsValue << "\": " << search_result_ad->value; - VLOG(1) << " \"" << kDataConversionTypeValue + VLOG(2) << " \"" << kDataRewardsValue << "\": " << search_result_ad->value; + VLOG(2) << " \"" << kDataConversionTypeValue << "\": " << search_result_ad->conversion->type; - VLOG(1) << " \"" << kDataConversionUrlPatternValue + VLOG(2) << " \"" << kDataConversionUrlPatternValue << "\": " << search_result_ad->conversion->url_pattern; - VLOG(1) << " \"" << kDataConversionAdvertiserPublicKeyValue + VLOG(2) << " \"" << kDataConversionAdvertiserPublicKeyValue << "\": " << search_result_ad->conversion->advertiser_public_key; - VLOG(1) << " \"" << kDataConversionObservationWindowValue + VLOG(2) << " \"" << kDataConversionObservationWindowValue << "\": " << search_result_ad->conversion->observation_window; } } @@ -325,23 +305,23 @@ void LogSearchResultAdMap(const SearchResultAdMap& search_result_ads) { } // namespace SearchResultAdMap ParseWebPageEntities(blink::mojom::WebPagePtr web_page) { + SearchResultAdMap search_result_ads; + if (!web_page) { + return search_result_ads; + } + for (const auto& entity : web_page->entities) { - if (entity->type != kProductType) { + if (!entity || entity->type != kProductType) { continue; } - absl::optional search_result_ads = - ParseSearchResultAdMapEntityProperties(entity); - - if (search_result_ads) { - LogSearchResultAdMap(*search_result_ads); - return std::move(*search_result_ads); + for (const auto& property : entity->properties) { + ParseWebPageEntityProperty(property, &search_result_ads); } } - VLOG(1) << "No search result ad found."; - - return {}; + LogSearchResultAdMap(search_result_ads); + return search_result_ads; } } // namespace brave_ads diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.h b/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h similarity index 63% rename from components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.h rename to components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h index 75dd0c370e5e..a1a619456a45 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing.h +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h @@ -3,22 +3,21 @@ * 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_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ -#define BRAVE_COMPONENTS_BRAVE_ADS_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ - -#include -#include +#ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ +#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ +#include "base/containers/flat_map.h" #include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom-forward.h" #include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom-forward.h" +#include "url/gurl.h" namespace brave_ads { using SearchResultAdMap = - std::map; + base::flat_map; SearchResultAdMap ParseWebPageEntities(blink::mojom::WebPagePtr web_page); } // namespace brave_ads -#endif // BRAVE_COMPONENTS_BRAVE_ADS_CONTENT_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ +#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc new file mode 100644 index 000000000000..83156d2094c5 --- /dev/null +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc @@ -0,0 +1,193 @@ +/* Copyright (c) 2022 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 + +#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h" +#include "brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h" +#include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" // IWYU pragma: keep +#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" +#include "url/gurl.h" + +namespace brave_ads { + +TEST(SearchResultAdParsingTest, ValidWebPage) { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_EQ(ads.size(), 1U); + const ads::mojom::SearchResultAdInfoPtr& search_result_ad = + ads.at(GURL(kTargetUrl)); + ASSERT_TRUE(search_result_ad.get()); + + EXPECT_EQ(search_result_ad->target_url, GURL(kTargetUrl)); + EXPECT_EQ(search_result_ad->value, 0.5); + EXPECT_EQ( + static_cast(search_result_ad->conversion->observation_window), + 1U); + + EXPECT_EQ(search_result_ad->creative_instance_id, kCreativeInstanceId); + EXPECT_EQ(search_result_ad->placement_id, "value0"); + EXPECT_EQ(search_result_ad->creative_set_id, "value1"); + EXPECT_EQ(search_result_ad->campaign_id, "value2"); + EXPECT_EQ(search_result_ad->advertiser_id, "value3"); + EXPECT_EQ(search_result_ad->headline_text, "value4"); + EXPECT_EQ(search_result_ad->description, "value5"); + EXPECT_EQ(search_result_ad->conversion->type, "value6"); + EXPECT_EQ(search_result_ad->conversion->url_pattern, "value7"); + EXPECT_EQ(search_result_ad->conversion->advertiser_public_key, "value8"); +} + +TEST(SearchResultAdParsingTest, NotValidWebPage) { + { + blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + web_page->entities[0]->type = "Not-Product"; + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + web_page->entities[0]->properties.clear(); + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + auto& property = web_page->entities[0]->properties[0]; + property->name = "not-creatives"; + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + auto& property = web_page->entities[0]->properties[0]; + property->values = schema_org::mojom::Values::NewEntityValues({}); + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + auto& property = web_page->entities[0]->properties[0]; + property->values = schema_org::mojom::Values::NewStringValues({"creative"}); + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } +} + +TEST(SearchResultAdParsingTest, NotValidAdEntityExtraProperty) { + { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + auto& property = web_page->entities[0]->properties[0]; + auto& ad_entity = property->values->get_entity_values()[0]; + ad_entity->type = "Not-SearchResultAd"; + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + auto& property = web_page->entities[0]->properties[0]; + auto& ad_entity = property->values->get_entity_values()[0]; + + schema_org::mojom::PropertyPtr extra_property = + schema_org::mojom::Property::New(); + extra_property->name = "extra-name"; + extra_property->values = + schema_org::mojom::Values::NewStringValues({"extra-value"}); + ad_entity->properties.push_back(std::move(extra_property)); + + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_FALSE(ads.empty()); + } +} + +TEST(SearchResultAdParsingTest, NotValidAdEntityPropertySkipped) { + constexpr int kSearchResultAdAttributesCount = 12; + for (int index = 0; index < kSearchResultAdAttributesCount; ++index) { + blink::mojom::WebPagePtr web_page = CreateTestWebPage(index); + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } +} + +TEST(SearchResultAdParsingTest, NotValidAdEntityWrongPropertyType) { + { + // Skip "data-landing-page". + blink::mojom::WebPagePtr web_page = CreateTestWebPage(0); + auto& property = web_page->entities[0]->properties[0]; + auto& ad_entity = property->values->get_entity_values()[0]; + + schema_org::mojom::PropertyPtr extra_property = + schema_org::mojom::Property::New(); + extra_property->name = "data-landing-page"; + extra_property->values = + schema_org::mojom::Values::NewStringValues({kTargetUrl}); + ad_entity->properties.push_back(std::move(extra_property)); + + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + // Skip "data-rewards-value". + blink::mojom::WebPagePtr web_page = CreateTestWebPage(1); + auto& property = web_page->entities[0]->properties[0]; + auto& ad_entity = property->values->get_entity_values()[0]; + + schema_org::mojom::PropertyPtr extra_property = + schema_org::mojom::Property::New(); + extra_property->name = "data-rewards-value"; + extra_property->values = + schema_org::mojom::Values::NewStringValues({"0-5"}); + ad_entity->properties.push_back(std::move(extra_property)); + + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + // Skip "data-conversion-observation-window-value". + blink::mojom::WebPagePtr web_page = CreateTestWebPage(2); + auto& property = web_page->entities[0]->properties[0]; + auto& ad_entity = property->values->get_entity_values()[0]; + + schema_org::mojom::PropertyPtr extra_property = + schema_org::mojom::Property::New(); + extra_property->name = "data-conversion-observation-window-value"; + extra_property->values = schema_org::mojom::Values::NewStringValues({"1"}); + ad_entity->properties.push_back(std::move(extra_property)); + + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } + + { + // Skip "data-creative-instance-id". + blink::mojom::WebPagePtr web_page = CreateTestWebPage(3); + auto& property = web_page->entities[0]->properties[0]; + auto& ad_entity = property->values->get_entity_values()[0]; + + schema_org::mojom::PropertyPtr extra_property = + schema_org::mojom::Property::New(); + extra_property->name = "data-creative-instance-id"; + extra_property->values = schema_org::mojom::Values::NewLongValues({101}); + ad_entity->properties.push_back(std::move(extra_property)); + + const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + EXPECT_TRUE(ads.empty()); + } +} + +} // namespace brave_ads diff --git a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc new file mode 100644 index 000000000000..ba6cf7a9af59 --- /dev/null +++ b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc @@ -0,0 +1,122 @@ +/* Copyright (c) 2022 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/search_result_ad/test_web_page_util.h" + +#include +#include +#include + +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" +#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" + +namespace brave_ads { + +namespace { + +schema_org::mojom::ValuesPtr CreateVectorValuesPtr(std::string value) { + return schema_org::mojom::Values::NewStringValues({std::move(value)}); +} + +schema_org::mojom::ValuesPtr CreateVectorValuesPtr(int64_t value) { + return schema_org::mojom::Values::NewLongValues({value}); +} + +class TestWebPageConstructor final { + public: + explicit TestWebPageConstructor(int attribute_index_to_skip) + : attribute_index_to_skip_(attribute_index_to_skip) { + web_page_ = CreateWebPage(); + } + ~TestWebPageConstructor() = default; + TestWebPageConstructor(const TestWebPageConstructor&) = delete; + TestWebPageConstructor& operator=(const TestWebPageConstructor&) = delete; + + blink::mojom::WebPagePtr GetTestWebPage() { return std::move(web_page_); } + + private: + blink::mojom::WebPagePtr CreateWebPage() { + blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); + schema_org::mojom::EntityPtr entity = schema_org::mojom::Entity::New(); + entity->type = "Product"; + schema_org::mojom::PropertyPtr property = + schema_org::mojom::Property::New(); + property->name = "creatives"; + + std::vector entity_values; + entity_values.push_back(CreateCreativeEntity()); + property->values = + schema_org::mojom::Values::NewEntityValues(std::move(entity_values)); + + entity->properties.push_back(std::move(property)); + web_page->entities.push_back(std::move(entity)); + + return web_page; + } + + template + void AddProperty(std::vector* properties, + base::StringPiece name, + T value) { + const int index = current_attribute_index_++; + if (index == attribute_index_to_skip_) { + return; + } + schema_org::mojom::PropertyPtr property = + schema_org::mojom::Property::New(); + property->name = static_cast(name); + property->values = CreateVectorValuesPtr(value); + + properties->push_back(std::move(property)); + } + + schema_org::mojom::EntityPtr CreateCreativeEntity() { + const char* kSearchResultAdStringAttributes[] = { + "data-placement-id", + "data-creative-set-id", + "data-campaign-id", + "data-advertiser-id", + "data-headline-text", + "data-description", + "data-conversion-type-value", + "data-conversion-url-pattern-value", + "data-conversion-advertiser-public-key-value"}; + + schema_org::mojom::EntityPtr entity = schema_org::mojom::Entity::New(); + entity->type = "SearchResultAd"; + + AddProperty(&entity->properties, "data-creative-instance-id", + kCreativeInstanceId); + AddProperty(&entity->properties, "data-landing-page", + kTargetUrl); + AddProperty(&entity->properties, "data-rewards-value", "0.5"); + AddProperty(&entity->properties, + "data-conversion-observation-window-value", 1); + + int index = 0; + for (const auto** it = std::begin(kSearchResultAdStringAttributes); + it != std::end(kSearchResultAdStringAttributes); ++it, ++index) { + AddProperty( + &entity->properties, *it, + std::string("value") + base::NumberToString(index)); + } + + return entity; + } + + blink::mojom::WebPagePtr web_page_; + int current_attribute_index_ = 0; + int attribute_index_to_skip_ = -1; +}; + +} // namespace + +blink::mojom::WebPagePtr CreateTestWebPage(int attribute_index_to_skip) { + TestWebPageConstructor constructor(attribute_index_to_skip); + return constructor.GetTestWebPage(); +} + +} // namespace brave_ads diff --git a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h new file mode 100644 index 000000000000..1d8d6e4060b5 --- /dev/null +++ b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2022 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_SEARCH_RESULT_AD_TEST_WEB_PAGE_UTIL_H_ +#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_TEST_WEB_PAGE_UTIL_H_ + +#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom-forward.h" + +namespace brave_ads { + +constexpr char kCreativeInstanceId[] = "creative_instance_id"; +constexpr char kTargetUrl[] = "https://brave.com"; + +blink::mojom::WebPagePtr CreateTestWebPage(int attribute_index_to_skip = -1); + +} // namespace brave_ads + +#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_TEST_WEB_PAGE_UTIL_H_ diff --git a/components/brave_ads/renderer/BUILD.gn b/components/brave_ads/renderer/BUILD.gn deleted file mode 100644 index 39744f3d2d6c..000000000000 --- a/components/brave_ads/renderer/BUILD.gn +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2023 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/. - -source_set("renderer") { - sources = [ - "search_result_ad_renderer_throttle.cc", - "search_result_ad_renderer_throttle.h", - ] - - deps = [ - "//base", - "//brave/components/brave_ads/common", - "//brave/components/brave_search/common", - "//content/public/renderer", - "//mojo/public/cpp/bindings", - "//third_party/blink/public:blink", - "//third_party/blink/public/common", - ] - - public_deps = [ "//brave/components/brave_ads/common:mojom" ] -} diff --git a/components/brave_ads/renderer/DEPS b/components/brave_ads/renderer/DEPS deleted file mode 100644 index 4e3b41445dfe..000000000000 --- a/components/brave_ads/renderer/DEPS +++ /dev/null @@ -1,8 +0,0 @@ -include_rules = [ - "+brave/components/brave_ads/common", - "+brave/components/brave_search/common", - "+content/public/renderer", - "+mojo/public/cpp/bindings", - "+services/network/public/cpp", - "+third_party/blink/public", -] diff --git a/components/brave_ads/renderer/search_result_ad_renderer_throttle.cc b/components/brave_ads/renderer/search_result_ad_renderer_throttle.cc deleted file mode 100644 index 2cc847baf026..000000000000 --- a/components/brave_ads/renderer/search_result_ad_renderer_throttle.cc +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (c) 2022 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/renderer/search_result_ad_renderer_throttle.h" - -#include -#include - -#include "base/feature_list.h" // IWYU pragma: keep -#include "brave/components/brave_ads/common/features.h" -#include "brave/components/brave_ads/common/search_result_ad_util.h" -#include "brave/components/brave_search/common/brave_search_utils.h" -#include "content/public/renderer/render_frame.h" -#include "services/network/public/cpp/resource_request.h" -#include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h" -#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" -#include "third_party/blink/public/platform/web_security_origin.h" -#include "third_party/blink/public/platform/web_url.h" -#include "third_party/blink/public/platform/web_url_request.h" -#include "url/gurl.h" - -namespace brave_ads { - -std::unique_ptr -SearchResultAdRendererThrottle::MaybeCreateThrottle( - int render_frame_id, - const blink::WebURLRequest& request) { - if (request.GetRequestContext() != blink::mojom::RequestContextType::FETCH || - !base::FeatureList::IsEnabled( - features::kSupportBraveSearchResultAdConfirmationEvents)) { - return nullptr; - } - - absl::optional top_frame_origin = - request.TopFrameOrigin(); - if (!top_frame_origin) { - return nullptr; - } - const GURL top_frame_origin_url = - static_cast(*top_frame_origin).GetURL(); - if (!brave_search::IsAllowedHost(top_frame_origin_url)) { - return nullptr; - } - - const GURL requestor_origin_url = - static_cast(request.RequestorOrigin()).GetURL(); - if (!brave_search::IsAllowedHost(requestor_origin_url)) { - return nullptr; - } - - const GURL url = static_cast(request.Url()); - if (!IsSearchResultAdViewedConfirmationUrl(url)) { - return nullptr; - } - - content::RenderFrame* render_frame = - content::RenderFrame::FromRoutingID(render_frame_id); - if (!render_frame || !render_frame->IsMainFrame()) { - return nullptr; - } - - mojo::PendingRemote brave_ads_pending_remote; - render_frame->GetBrowserInterfaceBroker()->GetInterface( - brave_ads_pending_remote.InitWithNewPipeAndPassReceiver()); - - auto throttle = std::make_unique( - std::move(brave_ads_pending_remote)); - - return throttle; -} - -SearchResultAdRendererThrottle::SearchResultAdRendererThrottle( - mojo::PendingRemote - brave_ads_pending_remote) - : brave_ads_pending_remote_(std::move(brave_ads_pending_remote)) { - DCHECK(brave_ads_pending_remote_); -} - -SearchResultAdRendererThrottle::~SearchResultAdRendererThrottle() = default; - -void SearchResultAdRendererThrottle::DetachFromCurrentSequence() {} - -void SearchResultAdRendererThrottle::WillStartRequest( - network::ResourceRequest* request, - bool* defer) { - DCHECK(request); - DCHECK(request->request_initiator); - DCHECK(brave_search::IsAllowedHost(request->request_initiator->GetURL())); - DCHECK_EQ(request->resource_type, - static_cast(blink::mojom::ResourceType::kXhr)); - DCHECK(request->is_fetch_like_api); - - const std::string creative_instance_id = - GetViewedSearchResultAdCreativeInstanceId(*request); - if (creative_instance_id.empty()) { - brave_ads_pending_remote_.reset(); - return; - } - - mojo::Remote brave_ads_remote( - std::move(brave_ads_pending_remote_)); - DCHECK(brave_ads_remote.is_bound()); - brave_ads_remote.reset_on_disconnect(); - - brave_ads::mojom::BraveAdsHost* raw_brave_ads_remote = brave_ads_remote.get(); - raw_brave_ads_remote->MaybeTriggerAdViewedEvent( - creative_instance_id, - base::BindOnce( - &SearchResultAdRendererThrottle::OnMaybeTriggerAdViewedEvent, - weak_factory_.GetWeakPtr(), std::move(brave_ads_remote))); - - *defer = true; -} - -void SearchResultAdRendererThrottle::OnMaybeTriggerAdViewedEvent( - mojo::Remote /*brave_ads_remote*/, - bool event_triggered) { - if (event_triggered) { - delegate_->CancelWithError(net::ERR_ABORTED); - } else { - delegate_->Resume(); - } -} - -} // namespace brave_ads diff --git a/components/brave_ads/renderer/search_result_ad_renderer_throttle.h b/components/brave_ads/renderer/search_result_ad_renderer_throttle.h deleted file mode 100644 index 246ae8a047bc..000000000000 --- a/components/brave_ads/renderer/search_result_ad_renderer_throttle.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2022 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_RENDERER_SEARCH_RESULT_AD_RENDERER_THROTTLE_H_ -#define BRAVE_COMPONENTS_BRAVE_ADS_RENDERER_SEARCH_RESULT_AD_RENDERER_THROTTLE_H_ - -#include - -#include "base/memory/weak_ptr.h" -#include "brave/components/brave_ads/common/brave_ads_host.mojom.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "third_party/blink/public/common/loader/url_loader_throttle.h" - -namespace blink { -class WebURLRequest; -} // namespace blink - -namespace brave_ads { - -// Monitors fetch ad viewed confirmation requests and cancels the request -// if the ad viewed event should be processed by the ads library. -class SearchResultAdRendererThrottle : public blink::URLLoaderThrottle { - public: - static std::unique_ptr MaybeCreateThrottle( - int render_frame_id, - const blink::WebURLRequest& request); - - explicit SearchResultAdRendererThrottle( - mojo::PendingRemote - brave_ads_pending_remote); - ~SearchResultAdRendererThrottle() override; - - SearchResultAdRendererThrottle(const SearchResultAdRendererThrottle&) = - delete; - SearchResultAdRendererThrottle& operator=( - const SearchResultAdRendererThrottle&) = delete; - - // Implements blink::URLLoaderThrottle: - void DetachFromCurrentSequence() override; - void WillStartRequest(network::ResourceRequest* request, - bool* defer) override; - - private: - void OnMaybeTriggerAdViewedEvent( - mojo::Remote brave_ads_remote, - bool event_triggered); - - mojo::PendingRemote brave_ads_pending_remote_; - base::WeakPtrFactory weak_factory_{this}; -}; - -} // namespace brave_ads - -#endif // BRAVE_COMPONENTS_BRAVE_ADS_RENDERER_SEARCH_RESULT_AD_RENDERER_THROTTLE_H_ diff --git a/renderer/BUILD.gn b/renderer/BUILD.gn index 29911d3daea0..7fd5f074c30e 100644 --- a/renderer/BUILD.gn +++ b/renderer/BUILD.gn @@ -18,7 +18,6 @@ source_set("renderer") { public_deps = [ "//chrome/renderer" ] deps = [ - "//brave/components/brave_ads/renderer", "//brave/components/brave_search/common", "//brave/components/brave_search/renderer", "//brave/components/brave_shields/common", diff --git a/renderer/brave_url_loader_throttle_provider.cc b/renderer/brave_url_loader_throttle_provider.cc deleted file mode 100644 index 7bfb91ee530d..000000000000 --- a/renderer/brave_url_loader_throttle_provider.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "brave/renderer/brave_url_loader_throttle_provider.h" - -#include - -#include "base/memory/ptr_util.h" -#include "brave/components/brave_ads/renderer/search_result_ad_renderer_throttle.h" -#include "chrome/renderer/chrome_content_renderer_client.h" -#include "chrome/renderer/url_loader_throttle_provider_impl.h" -#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h" - -BraveURLLoaderThrottleProvider::BraveURLLoaderThrottleProvider( - blink::ThreadSafeBrowserInterfaceBrokerProxy* broker, - blink::URLLoaderThrottleProviderType type, - ChromeContentRendererClient* chrome_content_renderer_client) - : provider_type_(type), - url_loader_throttle_provider_impl_( - std::make_unique( - broker, - type, - chrome_content_renderer_client)) {} - -BraveURLLoaderThrottleProvider::~BraveURLLoaderThrottleProvider() = default; - -BraveURLLoaderThrottleProvider::BraveURLLoaderThrottleProvider() = default; - -std::unique_ptr -BraveURLLoaderThrottleProvider::Clone() { - auto throttle_provider_clone = - base::WrapUnique(new BraveURLLoaderThrottleProvider()); - - throttle_provider_clone->provider_type_ = provider_type_; - throttle_provider_clone->url_loader_throttle_provider_impl_ = - url_loader_throttle_provider_impl_->Clone(); - return throttle_provider_clone; -} - -blink::WebVector> -BraveURLLoaderThrottleProvider::CreateThrottles( - int render_frame_id, - const blink::WebURLRequest& request) { - blink::WebVector> throttles = - url_loader_throttle_provider_impl_->CreateThrottles(render_frame_id, - request); - - if (provider_type_ == blink::URLLoaderThrottleProviderType::kFrame) { - auto search_result_ad_throttle = - brave_ads::SearchResultAdRendererThrottle::MaybeCreateThrottle( - render_frame_id, request); - if (search_result_ad_throttle) { - throttles.emplace_back(std::move(search_result_ad_throttle)); - } - } - - return throttles; -} - -void BraveURLLoaderThrottleProvider::SetOnline(bool is_online) { - url_loader_throttle_provider_impl_->SetOnline(is_online); -} diff --git a/renderer/brave_url_loader_throttle_provider.h b/renderer/brave_url_loader_throttle_provider.h deleted file mode 100644 index 08f2c12dad2c..000000000000 --- a/renderer/brave_url_loader_throttle_provider.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_RENDERER_BRAVE_URL_LOADER_THROTTLE_PROVIDER_H_ -#define BRAVE_RENDERER_BRAVE_URL_LOADER_THROTTLE_PROVIDER_H_ - -#include - -#include "third_party/blink/public/platform/url_loader_throttle_provider.h" - -class ChromeContentRendererClient; - -namespace blink { -class ThreadSafeBrowserInterfaceBrokerProxy; -} - -class BraveURLLoaderThrottleProvider : public blink::URLLoaderThrottleProvider { - public: - BraveURLLoaderThrottleProvider( - blink::ThreadSafeBrowserInterfaceBrokerProxy* broker, - blink::URLLoaderThrottleProviderType type, - ChromeContentRendererClient* chrome_content_renderer_client); - - BraveURLLoaderThrottleProvider(const BraveURLLoaderThrottleProvider& other) = - delete; - BraveURLLoaderThrottleProvider& operator=( - const BraveURLLoaderThrottleProvider&) = delete; - - ~BraveURLLoaderThrottleProvider() override; - - // blink::URLLoaderThrottleProvider implementation. - std::unique_ptr Clone() override; - blink::WebVector> CreateThrottles( - int render_frame_id, - const blink::WebURLRequest& request) override; - void SetOnline(bool is_online) override; - - private: - BraveURLLoaderThrottleProvider(); - - blink::URLLoaderThrottleProviderType provider_type_ = - blink::URLLoaderThrottleProviderType::kFrame; - - std::unique_ptr - url_loader_throttle_provider_impl_; -}; - -#endif // BRAVE_RENDERER_BRAVE_URL_LOADER_THROTTLE_PROVIDER_H_ diff --git a/renderer/sources.gni b/renderer/sources.gni index d105b552eb96..50a024a8a84b 100644 --- a/renderer/sources.gni +++ b/renderer/sources.gni @@ -12,13 +12,10 @@ brave_chrome_renderer_sources = [ "//brave/renderer/brave_content_renderer_client.h", "//brave/renderer/brave_render_thread_observer.cc", "//brave/renderer/brave_render_thread_observer.h", - "//brave/renderer/brave_url_loader_throttle_provider.cc", - "//brave/renderer/brave_url_loader_throttle_provider.h", ] brave_chrome_renderer_deps = [ "//brave/common:mojo_bindings", - "//brave/components/brave_ads/renderer", "//brave/components/brave_search/common", "//brave/components/brave_search/renderer", "//brave/components/brave_shields/common", diff --git a/test/BUILD.gn b/test/BUILD.gn index 54ff0b2286d2..2ebfcf6456fa 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -91,7 +91,6 @@ test("brave_unit_tests") { ] sources = [ - "//brave/browser/brave_ads/search_result_ad/search_result_ad_service_unittest.cc", "//brave/browser/brave_content_browser_client_unittest.cc", "//brave/browser/brave_resources_util_unittest.cc", "//brave/browser/brave_stats/brave_stats_updater_unittest.cc", @@ -111,8 +110,10 @@ test("brave_unit_tests") { "//brave/chromium_src/services/network/public/cpp/cors/cors_unittest.cc", "//brave/common/brave_content_client_unittest.cc", "//brave/components/assist_ranker/ranker_model_loader_impl_unittest.cc", - "//brave/components/brave_ads/common/search_result_ad_util_unittest.cc", - "//brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_parsing_unittest.cc", + "//brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc", + "//brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc", + "//brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc", + "//brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h", "//brave/components/brave_perf_predictor/browser/bandwidth_linreg_unittest.cc", "//brave/components/brave_perf_predictor/browser/bandwidth_savings_predictor_unittest.cc", "//brave/components/brave_perf_predictor/browser/named_third_party_registry_unittest.cc", @@ -190,6 +191,7 @@ test("brave_unit_tests") { "//brave/components/brave_ads/browser:test_support", "//brave/components/brave_ads/common", "//brave/components/brave_ads/content/browser/search_result_ad", + "//brave/components/brave_ads/core/browser/search_result_ad", "//brave/components/brave_ads/test:brave_ads_unit_tests", "//brave/components/brave_component_updater/browser", "//brave/components/brave_federated:brave_federated_tests", @@ -829,7 +831,7 @@ test("brave_browser_tests") { "//brave/components/brave_ads/browser", "//brave/components/brave_ads/browser:test_support", "//brave/components/brave_ads/common", - "//brave/components/brave_ads/content/browser/search_result_ad", + "//brave/components/brave_ads/core/browser/search_result_ad", "//brave/components/brave_component_updater/browser", "//brave/components/brave_perf_predictor/browser", "//brave/components/brave_perf_predictor/common", diff --git a/test/data/brave_ads/search_result_ad_broken.html b/test/data/brave_ads/search_result_ad_broken.html index d26ec47b9c4d..e5ca9af53c7d 100644 --- a/test/data/brave_ads/search_result_ad_broken.html +++ b/test/data/brave_ads/search_result_ad_broken.html @@ -12,7 +12,7 @@ "data-creative-set-id": "data-creative-set-id-1", "data-campaign-id": "data-campaign-id-1", "data-advertiser-id": "data-advertiser-id-1", - "data-landing-page": "https://brave.com/data-landing-page-1", + "data-landing-page": "https://example.com:REPLACE_WITH_HTTP_PORT/simple.html", "data-headline-text": "data-headline-text-1", "data-description": "data-description-1", "data-rewards-value": 1.5, @@ -24,33 +24,10 @@ ] } - - + + + Click me + + diff --git a/test/data/brave_ads/search_result_ad_sample.html b/test/data/brave_ads/search_result_ad_sample.html index a709ee848f31..b8a473230aaf 100644 --- a/test/data/brave_ads/search_result_ad_sample.html +++ b/test/data/brave_ads/search_result_ad_sample.html @@ -12,7 +12,7 @@ "data-creative-set-id": "data-creative-set-id-1", "data-campaign-id": "data-campaign-id-1", "data-advertiser-id": "data-advertiser-id-1", - "data-landing-page": "https://brave.com/data-landing-page-1", + "data-landing-page": "https://foo.com:REPLACE_WITH_HTTP_PORT/simple.html", "data-headline-text": "data-headline-text-1", "data-description": "data-description-1", "data-rewards-value": 1.5, @@ -20,15 +20,14 @@ "data-conversion-url-pattern-value": "data-conversion-url-pattern-value-1", "data-conversion-advertiser-public-key-value": "data-conversion-advertiser-public-key-value-1", "data-conversion-observation-window-value": 1 - }, - { + }, { "@type": "SearchResultAd", "data-placement-id": "data-placement-id-2", "data-creative-instance-id": "data-creative-instance-id-2", "data-creative-set-id": "data-creative-set-id-2", "data-campaign-id": "data-campaign-id-2", "data-advertiser-id": "data-advertiser-id-2", - "data-landing-page": "https://brave.com/data-landing-page-2", + "data-landing-page": "https://bar.com:REPLACE_WITH_HTTP_PORT/simple.html", "data-headline-text": "data-headline-text-2", "data-description": "data-description-2", "data-rewards-value": 2.5, @@ -40,30 +39,18 @@ ] } - - + + + + diff --git a/test/data/brave_ads/search_result_ad_with_redirect.html b/test/data/brave_ads/search_result_ad_with_redirect.html new file mode 100644 index 000000000000..eb7a72ccec21 --- /dev/null +++ b/test/data/brave_ads/search_result_ad_with_redirect.html @@ -0,0 +1,67 @@ + + + + Brave Search + + + + + + + + + + From 13e18cbfedfb205f037bc9d702d2948b3036de45 Mon Sep 17 00:00:00 2001 From: Aleksey Seren Date: Thu, 22 Dec 2022 21:35:02 -0500 Subject: [PATCH 2/4] Rename search result ad "Parse" term to "Convert". --- .../search_result_ad_handler.cc | 4 +- .../core/browser/search_result_ad/BUILD.gn | 4 +- ...cc => search_result_ad_converting_util.cc} | 73 +++++++++---------- ...g.h => search_result_ad_converting_util.h} | 9 ++- ...rch_result_ad_converting_util_unittest.cc} | 54 +++++++++----- test/BUILD.gn | 2 +- 6 files changed, 80 insertions(+), 66 deletions(-) rename components/brave_ads/core/browser/search_result_ad/{search_result_ad_parsing.cc => search_result_ad_converting_util.cc} (82%) rename components/brave_ads/core/browser/search_result_ad/{search_result_ad_parsing.h => search_result_ad_converting_util.h} (80%) rename components/brave_ads/core/browser/search_result_ad/{search_result_ad_parsing_unittest.cc => search_result_ad_converting_util_unittest.cc} (78%) diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc index e5c62098453d..c27664b242ce 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc @@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "brave/components/brave_ads/browser/ads_service.h" #include "brave/components/brave_ads/common/features.h" -#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h" +#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h" #include "brave/components/brave_search/common/brave_search_utils.h" #include "content/public/browser/render_frame_host.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -97,7 +97,7 @@ void SearchResultAdHandler::OnRetrieveSearchResultAdEntities( return; } - search_result_ads_ = ParseWebPageEntities(std::move(web_page)); + search_result_ads_ = ConvertWebPageToSearchResultAds(std::move(web_page)); if (search_result_ads_ && should_trigger_viewed_event_) { for (const auto& [key, search_result_ad] : *search_result_ads_) { diff --git a/components/brave_ads/core/browser/search_result_ad/BUILD.gn b/components/brave_ads/core/browser/search_result_ad/BUILD.gn index edb612a00b57..42c1d0f348fe 100644 --- a/components/brave_ads/core/browser/search_result_ad/BUILD.gn +++ b/components/brave_ads/core/browser/search_result_ad/BUILD.gn @@ -5,8 +5,8 @@ source_set("search_result_ad") { sources = [ - "search_result_ad_parsing.cc", - "search_result_ad_parsing.h", + "search_result_ad_converting_util.cc", + "search_result_ad_converting_util.h", ] deps = [ diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc similarity index 82% rename from components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.cc rename to components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc index 4897113a325c..298204e09760 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.cc +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc @@ -3,7 +3,7 @@ * 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/search_result_ad/search_result_ad_parsing.h" +#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h" #include #include @@ -193,8 +193,8 @@ bool SetSearchAdProperty(const schema_org::mojom::PropertyPtr& ad_property, return false; } -void ParseSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, - SearchResultAdMap* search_result_ads) { +void ConvertSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, + SearchResultAdMap* search_result_ads) { DCHECK(search_result_ads); // Wrong search result ad type specified. @@ -246,8 +246,9 @@ void ParseSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, std::move(search_result_ad)); } -void ParseWebPageEntityProperty(const schema_org::mojom::PropertyPtr& property, - SearchResultAdMap* search_result_ads) { +void ConvertWebPageEntityProperty( + const schema_org::mojom::PropertyPtr& property, + SearchResultAdMap* search_result_ads) { if (!property || property->name != kCreativesPropertyName) { return; } @@ -258,7 +259,7 @@ void ParseWebPageEntityProperty(const schema_org::mojom::PropertyPtr& property, } for (const auto& ad_entity : values->get_entity_values()) { - ParseSearchResultAdEntity(ad_entity, search_result_ads); + ConvertSearchResultAdEntity(ad_entity, search_result_ads); } } @@ -267,44 +268,42 @@ void LogSearchResultAdMap(const SearchResultAdMap& search_result_ads) { return; } - if (search_result_ads.empty()) { - return; - } - - VLOG(2) << "Parsed search result ads list:"; for (const auto& search_result_ad_pair : search_result_ads) { const auto& search_result_ad = search_result_ad_pair.second; - VLOG(2) << "Ad with \"" << kDataPlacementId - << "\": " << search_result_ad->placement_id; - VLOG(2) << " \"" << kDataCreativeInstanceId - << "\": " << search_result_ad->creative_instance_id; - VLOG(2) << " \"" << kDataCreativeSetId - << "\": " << search_result_ad->creative_set_id; - VLOG(2) << " \"" << kDataCampaignId - << "\": " << search_result_ad->campaign_id; - VLOG(2) << " \"" << kDataAdvertiserId - << "\": " << search_result_ad->advertiser_id; - VLOG(2) << " \"" << kDataLandingPage - << "\": " << search_result_ad->target_url; - VLOG(2) << " \"" << kDataHeadlineText - << "\": " << search_result_ad->headline_text; - VLOG(2) << " \"" << kDataDescription - << "\": " << search_result_ad->description; - VLOG(2) << " \"" << kDataRewardsValue << "\": " << search_result_ad->value; - VLOG(2) << " \"" << kDataConversionTypeValue - << "\": " << search_result_ad->conversion->type; - VLOG(2) << " \"" << kDataConversionUrlPatternValue - << "\": " << search_result_ad->conversion->url_pattern; - VLOG(2) << " \"" << kDataConversionAdvertiserPublicKeyValue - << "\": " << search_result_ad->conversion->advertiser_public_key; - VLOG(2) << " \"" << kDataConversionObservationWindowValue + VLOG(2) << "Converted search result ad with \"" << kDataPlacementId + << "\": " << search_result_ad->placement_id << "\n" + << " \"" << kDataCreativeInstanceId + << "\": " << search_result_ad->creative_instance_id << "\n" + << " \"" << kDataCreativeSetId + << "\": " << search_result_ad->creative_set_id << "\n" + << " \"" << kDataCampaignId + << "\": " << search_result_ad->campaign_id << "\n" + << " \"" << kDataAdvertiserId + << "\": " << search_result_ad->advertiser_id << "\n" + << " \"" << kDataLandingPage + << "\": " << search_result_ad->target_url << "\n" + << " \"" << kDataHeadlineText + << "\": " << search_result_ad->headline_text << "\n" + << " \"" << kDataDescription + << "\": " << search_result_ad->description << "\n" + << " \"" << kDataRewardsValue << "\": " << search_result_ad->value + << "\n" + << " \"" << kDataConversionTypeValue + << "\": " << search_result_ad->conversion->type << "\n" + << " \"" << kDataConversionUrlPatternValue + << "\": " << search_result_ad->conversion->url_pattern << "\n" + << " \"" << kDataConversionAdvertiserPublicKeyValue + << "\": " << search_result_ad->conversion->advertiser_public_key + << "\n" + << " \"" << kDataConversionObservationWindowValue << "\": " << search_result_ad->conversion->observation_window; } } } // namespace -SearchResultAdMap ParseWebPageEntities(blink::mojom::WebPagePtr web_page) { +SearchResultAdMap ConvertWebPageToSearchResultAds( + blink::mojom::WebPagePtr web_page) { SearchResultAdMap search_result_ads; if (!web_page) { return search_result_ads; @@ -316,7 +315,7 @@ SearchResultAdMap ParseWebPageEntities(blink::mojom::WebPagePtr web_page) { } for (const auto& property : entity->properties) { - ParseWebPageEntityProperty(property, &search_result_ads); + ConvertWebPageEntityProperty(property, &search_result_ads); } } diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h similarity index 80% rename from components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h rename to components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h index a1a619456a45..0d5147ce6836 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at https://mozilla.org/MPL/2.0/. */ -#ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ -#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ +#ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_CONVERTING_UTIL_H_ +#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_CONVERTING_UTIL_H_ #include "base/containers/flat_map.h" #include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom-forward.h" @@ -16,8 +16,9 @@ namespace brave_ads { using SearchResultAdMap = base::flat_map; -SearchResultAdMap ParseWebPageEntities(blink::mojom::WebPagePtr web_page); +SearchResultAdMap ConvertWebPageToSearchResultAds( + blink::mojom::WebPagePtr web_page); } // namespace brave_ads -#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_PARSING_H_ +#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_CONVERTING_UTIL_H_ diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc similarity index 78% rename from components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc rename to components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc index 83156d2094c5..531eadff912f 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc @@ -5,7 +5,7 @@ #include -#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing.h" +#include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h" #include "brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h" #include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom.h" #include "testing/gtest/include/gtest/gtest.h" // IWYU pragma: keep @@ -14,9 +14,10 @@ namespace brave_ads { -TEST(SearchResultAdParsingTest, ValidWebPage) { +TEST(SearchResultAdConvertingTest, ValidWebPage) { blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_EQ(ads.size(), 1U); const ads::mojom::SearchResultAdInfoPtr& search_result_ad = ads.at(GURL(kTargetUrl)); @@ -40,24 +41,27 @@ TEST(SearchResultAdParsingTest, ValidWebPage) { EXPECT_EQ(search_result_ad->conversion->advertiser_public_key, "value8"); } -TEST(SearchResultAdParsingTest, NotValidWebPage) { +TEST(SearchResultAdConvertingTest, NotValidWebPage) { { blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } { blink::mojom::WebPagePtr web_page = CreateTestWebPage(); web_page->entities[0]->type = "Not-Product"; - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } { blink::mojom::WebPagePtr web_page = CreateTestWebPage(); web_page->entities[0]->properties.clear(); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } @@ -65,7 +69,8 @@ TEST(SearchResultAdParsingTest, NotValidWebPage) { blink::mojom::WebPagePtr web_page = CreateTestWebPage(); auto& property = web_page->entities[0]->properties[0]; property->name = "not-creatives"; - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } @@ -73,7 +78,8 @@ TEST(SearchResultAdParsingTest, NotValidWebPage) { blink::mojom::WebPagePtr web_page = CreateTestWebPage(); auto& property = web_page->entities[0]->properties[0]; property->values = schema_org::mojom::Values::NewEntityValues({}); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } @@ -81,18 +87,20 @@ TEST(SearchResultAdParsingTest, NotValidWebPage) { blink::mojom::WebPagePtr web_page = CreateTestWebPage(); auto& property = web_page->entities[0]->properties[0]; property->values = schema_org::mojom::Values::NewStringValues({"creative"}); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } } -TEST(SearchResultAdParsingTest, NotValidAdEntityExtraProperty) { +TEST(SearchResultAdConvertingTest, NotValidAdEntityExtraProperty) { { blink::mojom::WebPagePtr web_page = CreateTestWebPage(); auto& property = web_page->entities[0]->properties[0]; auto& ad_entity = property->values->get_entity_values()[0]; ad_entity->type = "Not-SearchResultAd"; - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } @@ -108,21 +116,23 @@ TEST(SearchResultAdParsingTest, NotValidAdEntityExtraProperty) { schema_org::mojom::Values::NewStringValues({"extra-value"}); ad_entity->properties.push_back(std::move(extra_property)); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_FALSE(ads.empty()); } } -TEST(SearchResultAdParsingTest, NotValidAdEntityPropertySkipped) { +TEST(SearchResultAdConvertingTest, NotValidAdEntityPropertySkipped) { constexpr int kSearchResultAdAttributesCount = 12; for (int index = 0; index < kSearchResultAdAttributesCount; ++index) { blink::mojom::WebPagePtr web_page = CreateTestWebPage(index); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } } -TEST(SearchResultAdParsingTest, NotValidAdEntityWrongPropertyType) { +TEST(SearchResultAdConvertingTest, NotValidAdEntityWrongPropertyType) { { // Skip "data-landing-page". blink::mojom::WebPagePtr web_page = CreateTestWebPage(0); @@ -136,7 +146,8 @@ TEST(SearchResultAdParsingTest, NotValidAdEntityWrongPropertyType) { schema_org::mojom::Values::NewStringValues({kTargetUrl}); ad_entity->properties.push_back(std::move(extra_property)); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } @@ -153,7 +164,8 @@ TEST(SearchResultAdParsingTest, NotValidAdEntityWrongPropertyType) { schema_org::mojom::Values::NewStringValues({"0-5"}); ad_entity->properties.push_back(std::move(extra_property)); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } @@ -169,7 +181,8 @@ TEST(SearchResultAdParsingTest, NotValidAdEntityWrongPropertyType) { extra_property->values = schema_org::mojom::Values::NewStringValues({"1"}); ad_entity->properties.push_back(std::move(extra_property)); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } @@ -185,7 +198,8 @@ TEST(SearchResultAdParsingTest, NotValidAdEntityWrongPropertyType) { extra_property->values = schema_org::mojom::Values::NewLongValues({101}); ad_entity->properties.push_back(std::move(extra_property)); - const SearchResultAdMap ads = ParseWebPageEntities(std::move(web_page)); + const SearchResultAdMap ads = + ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_TRUE(ads.empty()); } } diff --git a/test/BUILD.gn b/test/BUILD.gn index 2ebfcf6456fa..08cbc4de082b 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -111,7 +111,7 @@ test("brave_unit_tests") { "//brave/common/brave_content_client_unittest.cc", "//brave/components/assist_ranker/ranker_model_loader_impl_unittest.cc", "//brave/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc", - "//brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_parsing_unittest.cc", + "//brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc", "//brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc", "//brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h", "//brave/components/brave_perf_predictor/browser/bandwidth_linreg_unittest.cc", From 74ea266effb359d7cb62d64fecc2c0ad6091021a Mon Sep 17 00:00:00 2001 From: Aleksey Seren Date: Tue, 17 Jan 2023 10:56:33 -0500 Subject: [PATCH 3/4] Changed verbose log level. --- .../search_result_ad_tab_helper.cc | 8 +++---- .../search_result_ad_tab_helper.h | 7 +++--- .../search_result_ad_handler.cc | 23 +++++++++++-------- .../search_result_ad_handler.h | 2 +- .../search_result_ad_handler_unittest.cc | 23 ++++++++----------- .../core/browser/search_result_ad/BUILD.gn | 2 +- .../search_result_ad_converting_util.cc | 22 +++++++++--------- .../search_result_ad_converting_util.h | 2 +- ...arch_result_ad_converting_util_unittest.cc | 11 +++++---- .../search_result_ad/test_web_page_util.cc | 6 ++--- .../search_result_ad/test_web_page_util.h | 6 ++--- 11 files changed, 56 insertions(+), 56 deletions(-) diff --git a/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc index 66d9187f225a..b1581762d2f0 100644 --- a/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc +++ b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.cc @@ -14,13 +14,12 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" +#include "url/gurl.h" namespace brave_ads { namespace { - AdsService* g_ads_service_for_testing = nullptr; - } // namespace SearchResultAdTabHelper::SearchResultAdTabHelper( @@ -53,6 +52,7 @@ void SearchResultAdTabHelper::MaybeTriggerSearchResultAdClickedEvent( // static void SearchResultAdTabHelper::SetAdsServiceForTesting(AdsService* ads_service) { + DCHECK(!g_ads_service_for_testing || !ads_service); g_ads_service_for_testing = ads_service; } @@ -74,7 +74,7 @@ void SearchResultAdTabHelper::DidFinishNavigation( return; } - ProcessPossibleSearchResultAdClickedEvent(navigation_handle); + MaybeProcessSearchResultAdClickedEvent(navigation_handle); const bool should_trigger_viewed_event = navigation_handle->GetRestoreType() == content::RestoreType::kNotRestored; @@ -96,7 +96,7 @@ void SearchResultAdTabHelper::WebContentsDestroyed() { search_result_ad_handler_.reset(); } -void SearchResultAdTabHelper::ProcessPossibleSearchResultAdClickedEvent( +void SearchResultAdTabHelper::MaybeProcessSearchResultAdClickedEvent( content::NavigationHandle* navigation_handle) { DCHECK(navigation_handle); diff --git a/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h index 97cdc1bd49b9..1b9817be64fb 100644 --- a/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h +++ b/browser/brave_ads/search_result_ad/search_result_ad_tab_helper.h @@ -14,11 +14,12 @@ #include "mojo/public/cpp/bindings/remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" -#include "url/gurl.h" + +class GURL; namespace content { class RenderFrameHost; -} +} // namespace content namespace brave_ads { @@ -55,7 +56,7 @@ class SearchResultAdTabHelper void DocumentOnLoadCompletedInPrimaryMainFrame() override; void WebContentsDestroyed() override; - void ProcessPossibleSearchResultAdClickedEvent( + void MaybeProcessSearchResultAdClickedEvent( content::NavigationHandle* navigation_handle); std::unique_ptr search_result_ad_handler_; diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc index c27664b242ce..2dd516f33837 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ @@ -14,11 +14,13 @@ #include "brave/components/brave_search/common/brave_search_utils.h" #include "content/public/browser/render_frame_host.h" #include "services/service_manager/public/cpp/interface_provider.h" +#include "url/url_constants.h" namespace brave_ads { -SearchResultAdHandler::SearchResultAdHandler(AdsService* ads_service, - bool should_trigger_viewed_event) +SearchResultAdHandler::SearchResultAdHandler( + AdsService* ads_service, + const bool should_trigger_viewed_event) : ads_service_(ads_service), should_trigger_viewed_event_(should_trigger_viewed_event) { DCHECK(ads_service_); @@ -31,7 +33,7 @@ std::unique_ptr SearchResultAdHandler::MaybeCreateSearchResultAdHandler( AdsService* ads_service, const GURL& url, - bool should_trigger_viewed_event) { + const bool should_trigger_viewed_event) { if (!ads_service || !ads_service->IsEnabled() || !base::FeatureList::IsEnabled( features::kSupportBraveSearchResultAdConfirmationEvents) || @@ -67,10 +69,10 @@ void SearchResultAdHandler::MaybeRetrieveSearchResultAd( void SearchResultAdHandler::MaybeTriggerSearchResultAdClickedEvent( const GURL& navigation_url) { - DCHECK(navigation_url.is_valid()); DCHECK(ads_service_); - - if (!ads_service_->IsEnabled() || !search_result_ads_) { + if (!ads_service_->IsEnabled() || !search_result_ads_ || + !navigation_url.is_valid() || + !navigation_url.SchemeIs(url::kHttpsScheme)) { return; } @@ -80,9 +82,10 @@ void SearchResultAdHandler::MaybeTriggerSearchResultAdClickedEvent( } const ads::mojom::SearchResultAdInfoPtr& search_result_ad = it->second; - DCHECK(search_result_ad); - DCHECK(search_result_ad->target_url.is_valid() && - search_result_ad->target_url.SchemeIs(url::kHttpsScheme)); + if (!search_result_ad || !search_result_ad->target_url.is_valid() || + !search_result_ad->target_url.SchemeIs(url::kHttpsScheme)) { + return; + } ads_service_->TriggerSearchResultAdEvent( search_result_ad->Clone(), ads::mojom::SearchResultAdEventType::kClicked); diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h index 5880d681f86e..ddca72522a97 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc index 4e355535217e..263950a17ad4 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ @@ -15,13 +15,13 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -namespace brave_ads { -namespace { - using testing::_; using testing::Mock; using testing::Return; +namespace brave_ads { +namespace { + constexpr char kAllowedDomain[] = "https://search.brave.com"; constexpr char kNotAllowedDomain[] = "https://brave.com"; @@ -33,11 +33,6 @@ class SearchResultAdHandlerTest : public ::testing::Test { feature_list_.InitAndEnableFeature( features::kSupportBraveSearchResultAdConfirmationEvents); } - ~SearchResultAdHandlerTest() override = default; - - SearchResultAdHandlerTest(const SearchResultAdHandlerTest&) = delete; - SearchResultAdHandlerTest& operator=(const SearchResultAdHandlerTest&) = - delete; static void SimulateOnRetrieveSearchResultAdEntities( SearchResultAdHandler* search_result_ad_handler, @@ -105,7 +100,7 @@ TEST_F(SearchResultAdHandlerTest, BraveAdsEmpty) { blink::mojom::WebPage::New()); search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( - GURL(kTargetUrl)); + GURL(kTestWebPageTargetUrl)); } TEST_F(SearchResultAdHandlerTest, BraveAdsBecomeDisabled) { @@ -132,7 +127,7 @@ TEST_F(SearchResultAdHandlerTest, BraveAdsBecomeDisabled) { CreateTestWebPage()); search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( - GURL(kTargetUrl)); + GURL(kTestWebPageTargetUrl)); } TEST_F(SearchResultAdHandlerTest, BraveAdsViewedClicked) { @@ -155,10 +150,10 @@ TEST_F(SearchResultAdHandlerTest, BraveAdsViewedClicked) { CreateTestWebPage()); search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( - GURL(kTargetUrl)); + GURL(kTestWebPageTargetUrl)); search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( - GURL(kTargetUrl)); + GURL(kTestWebPageTargetUrl)); } TEST_F(SearchResultAdHandlerTest, BraveAdsTabRestored) { @@ -181,7 +176,7 @@ TEST_F(SearchResultAdHandlerTest, BraveAdsTabRestored) { CreateTestWebPage()); search_result_ad_handler->MaybeTriggerSearchResultAdClickedEvent( - GURL(kTargetUrl)); + GURL(kTestWebPageTargetUrl)); } } // namespace brave_ads diff --git a/components/brave_ads/core/browser/search_result_ad/BUILD.gn b/components/brave_ads/core/browser/search_result_ad/BUILD.gn index 42c1d0f348fe..6252cff4edbd 100644 --- a/components/brave_ads/core/browser/search_result_ad/BUILD.gn +++ b/components/brave_ads/core/browser/search_result_ad/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Brave Authors. All rights reserved. +# Copyright (c) 2023 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/. diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc index 298204e09760..4f557920f470 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ @@ -193,12 +193,12 @@ bool SetSearchAdProperty(const schema_org::mojom::PropertyPtr& ad_property, return false; } -void ConvertSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, - SearchResultAdMap* search_result_ads) { +void ConvertEntityToSearchResultAd(const schema_org::mojom::EntityPtr& entity, + SearchResultAdMap* search_result_ads) { DCHECK(search_result_ads); // Wrong search result ad type specified. - if (!ad_entity || ad_entity->type != kSearchResultAdType) { + if (!entity || entity->type != kSearchResultAdType) { return; } @@ -206,7 +206,7 @@ void ConvertSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, search_result_ad->conversion = ConversionInfo::New(); base::flat_set found_attributes; - for (const auto& ad_property : ad_entity->properties) { + for (const auto& ad_property : entity->properties) { if (!ad_property) { return; } @@ -221,7 +221,7 @@ void ConvertSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, found_attributes.insert(*it); if (!SetSearchAdProperty(ad_property, search_result_ad.get())) { - VLOG(2) << "Cannot read search result ad attribute value: " + VLOG(6) << "Cannot read search result ad attribute value: " << ad_property->name; return; } @@ -235,7 +235,7 @@ void ConvertSearchResultAdEntity(const schema_org::mojom::EntityPtr& ad_entity, found_attributes.begin(), found_attributes.end(), std::back_inserter(absent_attributes)); - VLOG(2) << "Some of search result ad attributes were not specified: " + VLOG(6) << "Some of search result ad attributes were not specified: " << base::JoinString(absent_attributes, ", "); return; @@ -258,19 +258,19 @@ void ConvertWebPageEntityProperty( return; } - for (const auto& ad_entity : values->get_entity_values()) { - ConvertSearchResultAdEntity(ad_entity, search_result_ads); + for (const auto& entity : values->get_entity_values()) { + ConvertEntityToSearchResultAd(entity, search_result_ads); } } void LogSearchResultAdMap(const SearchResultAdMap& search_result_ads) { - if (!VLOG_IS_ON(2)) { + if (!VLOG_IS_ON(6)) { return; } for (const auto& search_result_ad_pair : search_result_ads) { const auto& search_result_ad = search_result_ad_pair.second; - VLOG(2) << "Converted search result ad with \"" << kDataPlacementId + VLOG(6) << "Converted search result ad with \"" << kDataPlacementId << "\": " << search_result_ad->placement_id << "\n" << " \"" << kDataCreativeInstanceId << "\": " << search_result_ad->creative_instance_id << "\n" diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h index 0d5147ce6836..ee2b2bdfa70b 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc index 531eadff912f..a0755e9c0af9 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ @@ -20,16 +20,17 @@ TEST(SearchResultAdConvertingTest, ValidWebPage) { ConvertWebPageToSearchResultAds(std::move(web_page)); EXPECT_EQ(ads.size(), 1U); const ads::mojom::SearchResultAdInfoPtr& search_result_ad = - ads.at(GURL(kTargetUrl)); + ads.at(GURL(kTestWebPageTargetUrl)); ASSERT_TRUE(search_result_ad.get()); - EXPECT_EQ(search_result_ad->target_url, GURL(kTargetUrl)); + EXPECT_EQ(search_result_ad->target_url, GURL(kTestWebPageTargetUrl)); EXPECT_EQ(search_result_ad->value, 0.5); EXPECT_EQ( static_cast(search_result_ad->conversion->observation_window), 1U); - EXPECT_EQ(search_result_ad->creative_instance_id, kCreativeInstanceId); + EXPECT_EQ(search_result_ad->creative_instance_id, + kTestWebPageCreativeInstanceId); EXPECT_EQ(search_result_ad->placement_id, "value0"); EXPECT_EQ(search_result_ad->creative_set_id, "value1"); EXPECT_EQ(search_result_ad->campaign_id, "value2"); @@ -143,7 +144,7 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityWrongPropertyType) { schema_org::mojom::Property::New(); extra_property->name = "data-landing-page"; extra_property->values = - schema_org::mojom::Values::NewStringValues({kTargetUrl}); + schema_org::mojom::Values::NewStringValues({kTestWebPageTargetUrl}); ad_entity->properties.push_back(std::move(extra_property)); const SearchResultAdMap ads = diff --git a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc index ba6cf7a9af59..0ed4301735f7 100644 --- a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc +++ b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ @@ -89,9 +89,9 @@ class TestWebPageConstructor final { entity->type = "SearchResultAd"; AddProperty(&entity->properties, "data-creative-instance-id", - kCreativeInstanceId); + kTestWebPageCreativeInstanceId); AddProperty(&entity->properties, "data-landing-page", - kTargetUrl); + kTestWebPageTargetUrl); AddProperty(&entity->properties, "data-rewards-value", "0.5"); AddProperty(&entity->properties, "data-conversion-observation-window-value", 1); diff --git a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h index 1d8d6e4060b5..146a0b7d5846 100644 --- a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h +++ b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2022 The Brave Authors. All rights reserved. +/* Copyright (c) 2023 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/. */ @@ -10,8 +10,8 @@ namespace brave_ads { -constexpr char kCreativeInstanceId[] = "creative_instance_id"; -constexpr char kTargetUrl[] = "https://brave.com"; +constexpr char kTestWebPageCreativeInstanceId[] = "creative_instance_id"; +constexpr char kTestWebPageTargetUrl[] = "https://brave.com"; blink::mojom::WebPagePtr CreateTestWebPage(int attribute_index_to_skip = -1); From b32ae234cf7274ff2112a365f089c5e407483c90 Mon Sep 17 00:00:00 2001 From: Aleksey Seren Date: Wed, 25 Jan 2023 12:24:14 -0500 Subject: [PATCH 4/4] Remove blink deps from /brave/components/brave_ads/core. --- browser/brave_ads/sources.gni | 2 +- .../brave_ads/common/brave_ads_host.mojom | 9 -- .../browser/{search_result_ad => }/BUILD.gn | 8 +- .../search_result_ad_handler.cc | 3 +- .../search_result_ad_handler_unittest.cc | 6 ++ components/brave_ads/core/DEPS | 4 + .../browser/{search_result_ad => }/BUILD.gn | 11 +-- .../core/browser/search_result_ad/DEPS | 4 - .../search_result_ad_converting_util.cc | 31 +++---- .../search_result_ad_converting_util.h | 8 +- ...arch_result_ad_converting_util_unittest.cc | 92 +++++++++++-------- .../search_result_ad/test_web_page_util.cc | 35 ++++--- .../search_result_ad/test_web_page_util.h | 7 +- test/BUILD.gn | 7 +- 14 files changed, 118 insertions(+), 109 deletions(-) delete mode 100644 components/brave_ads/common/brave_ads_host.mojom rename components/brave_ads/content/browser/{search_result_ad => }/BUILD.gn (81%) create mode 100644 components/brave_ads/core/DEPS rename components/brave_ads/core/browser/{search_result_ad => }/BUILD.gn (62%) delete mode 100644 components/brave_ads/core/browser/search_result_ad/DEPS diff --git a/browser/brave_ads/sources.gni b/browser/brave_ads/sources.gni index 4179657de24d..470a9f7b92f0 100644 --- a/browser/brave_ads/sources.gni +++ b/browser/brave_ads/sources.gni @@ -31,7 +31,7 @@ brave_browser_brave_ads_deps = [ "//brave/browser/ui/brave_ads", "//brave/components/brave_ads/browser", "//brave/components/brave_ads/common", - "//brave/components/brave_ads/content/browser/search_result_ad", + "//brave/components/brave_ads/content/browser", "//brave/components/brave_federated", "//brave/components/brave_federated/public/interfaces", "//brave/components/brave_rewards/browser", diff --git a/components/brave_ads/common/brave_ads_host.mojom b/components/brave_ads/common/brave_ads_host.mojom deleted file mode 100644 index df94cc34ab57..000000000000 --- a/components/brave_ads/common/brave_ads_host.mojom +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright (c) 2023 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/. */ -module brave_ads.mojom; - -interface BraveAdsHost { - MaybeTriggerAdViewedEvent(string creative_instance_id) => (bool event_triggered); -}; diff --git a/components/brave_ads/content/browser/search_result_ad/BUILD.gn b/components/brave_ads/content/browser/BUILD.gn similarity index 81% rename from components/brave_ads/content/browser/search_result_ad/BUILD.gn rename to components/brave_ads/content/browser/BUILD.gn index 1a1dc29f5726..e0ee0e00f92b 100644 --- a/components/brave_ads/content/browser/search_result_ad/BUILD.gn +++ b/components/brave_ads/content/browser/BUILD.gn @@ -3,17 +3,17 @@ # 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/. -source_set("search_result_ad") { +static_library("browser") { sources = [ - "search_result_ad_handler.cc", - "search_result_ad_handler.h", + "search_result_ad/search_result_ad_handler.cc", + "search_result_ad/search_result_ad_handler.h", ] deps = [ "//base", "//brave/components/brave_ads/browser", "//brave/components/brave_ads/common", - "//brave/components/brave_ads/core/browser/search_result_ad", + "//brave/components/brave_ads/core/browser", "//brave/components/brave_search/common", "//components/schema_org/common:mojom", "//content/public/browser", diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc index 2dd516f33837..4758322fd975 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler.cc @@ -100,7 +100,8 @@ void SearchResultAdHandler::OnRetrieveSearchResultAdEntities( return; } - search_result_ads_ = ConvertWebPageToSearchResultAds(std::move(web_page)); + search_result_ads_ = + ConvertWebPageEntitiesToSearchResultAds(web_page->entities); if (search_result_ads_ && should_trigger_viewed_event_) { for (const auto& [key, search_result_ad] : *search_result_ads_) { diff --git a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc index 263950a17ad4..01ae99dcaf58 100644 --- a/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc +++ b/components/brave_ads/content/browser/search_result_ad/search_result_ad_handler_unittest.cc @@ -25,6 +25,12 @@ namespace { constexpr char kAllowedDomain[] = "https://search.brave.com"; constexpr char kNotAllowedDomain[] = "https://brave.com"; +blink::mojom::WebPagePtr CreateTestWebPage() { + blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); + web_page->entities = CreateTestWebPageEntities(); + return web_page; +} + } // namespace class SearchResultAdHandlerTest : public ::testing::Test { diff --git a/components/brave_ads/core/DEPS b/components/brave_ads/core/DEPS new file mode 100644 index 000000000000..c82b33a6b27a --- /dev/null +++ b/components/brave_ads/core/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "-content", + "-third_party/blink", +] diff --git a/components/brave_ads/core/browser/search_result_ad/BUILD.gn b/components/brave_ads/core/browser/BUILD.gn similarity index 62% rename from components/brave_ads/core/browser/search_result_ad/BUILD.gn rename to components/brave_ads/core/browser/BUILD.gn index 6252cff4edbd..c84dfd762355 100644 --- a/components/brave_ads/core/browser/search_result_ad/BUILD.gn +++ b/components/brave_ads/core/browser/BUILD.gn @@ -3,22 +3,19 @@ # 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/. -source_set("search_result_ad") { +static_library("browser") { sources = [ - "search_result_ad_converting_util.cc", - "search_result_ad_converting_util.h", + "search_result_ad/search_result_ad_converting_util.cc", + "search_result_ad/search_result_ad_converting_util.h", ] deps = [ "//base", - "//components/schema_org/common:mojom", - "//services/network/public/cpp", - "//third_party/abseil-cpp:absl", "//url", ] public_deps = [ "//brave/vendor/bat-native-ads", - "//third_party/blink/public/mojom:mojom_platform_headers", + "//components/schema_org/common:mojom", ] } diff --git a/components/brave_ads/core/browser/search_result_ad/DEPS b/components/brave_ads/core/browser/search_result_ad/DEPS deleted file mode 100644 index 7739ebf24138..000000000000 --- a/components/brave_ads/core/browser/search_result_ad/DEPS +++ /dev/null @@ -1,4 +0,0 @@ -include_rules = [ - "+services/network/public/cpp", - "+third_party/blink/public", -] diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc index 4f557920f470..3be7e4b86325 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.cc @@ -5,17 +5,17 @@ #include "brave/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h" +#include #include #include #include #include "base/containers/fixed_flat_set.h" #include "base/containers/flat_set.h" +#include "base/logging.h" #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom.h" -#include "components/schema_org/common/metadata.mojom.h" -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" using ads::mojom::ConversionInfo; using ads::mojom::ConversionInfoPtr; @@ -229,14 +229,16 @@ void ConvertEntityToSearchResultAd(const schema_org::mojom::EntityPtr& entity, // Not all of attributes were specified. if (found_attributes.size() != kSearchResultAdAttributes.size()) { - std::vector absent_attributes; - std::set_difference(kSearchResultAdAttributes.begin(), - kSearchResultAdAttributes.end(), - found_attributes.begin(), found_attributes.end(), - std::back_inserter(absent_attributes)); - - VLOG(6) << "Some of search result ad attributes were not specified: " - << base::JoinString(absent_attributes, ", "); + if (VLOG_IS_ON(6)) { + std::vector absent_attributes; + base::ranges::set_difference( + kSearchResultAdAttributes.cbegin(), kSearchResultAdAttributes.cend(), + found_attributes.cbegin(), found_attributes.cend(), + std::back_inserter(absent_attributes)); + + VLOG(6) << "Some of search result ad attributes were not specified: " + << base::JoinString(absent_attributes, ", "); + } return; } @@ -302,14 +304,11 @@ void LogSearchResultAdMap(const SearchResultAdMap& search_result_ads) { } // namespace -SearchResultAdMap ConvertWebPageToSearchResultAds( - blink::mojom::WebPagePtr web_page) { +SearchResultAdMap ConvertWebPageEntitiesToSearchResultAds( + const std::vector<::schema_org::mojom::EntityPtr>& web_page_entities) { SearchResultAdMap search_result_ads; - if (!web_page) { - return search_result_ads; - } - for (const auto& entity : web_page->entities) { + for (const auto& entity : web_page_entities) { if (!entity || entity->type != kProductType) { continue; } diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h index ee2b2bdfa70b..34a98335179a 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util.h @@ -6,9 +6,11 @@ #ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_CONVERTING_UTIL_H_ #define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_SEARCH_RESULT_AD_CONVERTING_UTIL_H_ +#include + #include "base/containers/flat_map.h" #include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom-forward.h" -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom-forward.h" +#include "components/schema_org/common/metadata.mojom.h" #include "url/gurl.h" namespace brave_ads { @@ -16,8 +18,8 @@ namespace brave_ads { using SearchResultAdMap = base::flat_map; -SearchResultAdMap ConvertWebPageToSearchResultAds( - blink::mojom::WebPagePtr web_page); +SearchResultAdMap ConvertWebPageEntitiesToSearchResultAds( + const std::vector<::schema_org::mojom::EntityPtr>& web_page_entities); } // namespace brave_ads diff --git a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc index a0755e9c0af9..1b98f2a4ceb2 100644 --- a/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc +++ b/components/brave_ads/core/browser/search_result_ad/search_result_ad_converting_util_unittest.cc @@ -9,15 +9,15 @@ #include "brave/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h" #include "brave/vendor/bat-native-ads/include/bat/ads/public/interfaces/ads.mojom.h" #include "testing/gtest/include/gtest/gtest.h" // IWYU pragma: keep -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" #include "url/gurl.h" namespace brave_ads { TEST(SearchResultAdConvertingTest, ValidWebPage) { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_EQ(ads.size(), 1U); const ads::mojom::SearchResultAdInfoPtr& search_result_ad = ads.at(GURL(kTestWebPageTargetUrl)); @@ -44,70 +44,77 @@ TEST(SearchResultAdConvertingTest, ValidWebPage) { TEST(SearchResultAdConvertingTest, NotValidWebPage) { { - blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); + std::vector<::schema_org::mojom::EntityPtr> entities; const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - web_page->entities[0]->type = "Not-Product"; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); + entities[0]->type = "Not-Product"; const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - web_page->entities[0]->properties.clear(); + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); + entities[0]->properties.clear(); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); + auto& property = entities[0]->properties[0]; property->name = "not-creatives"; const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); + auto& property = entities[0]->properties[0]; property->values = schema_org::mojom::Values::NewEntityValues({}); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); + auto& property = entities[0]->properties[0]; property->values = schema_org::mojom::Values::NewStringValues({"creative"}); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } } TEST(SearchResultAdConvertingTest, NotValidAdEntityExtraProperty) { { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); + auto& property = entities[0]->properties[0]; auto& ad_entity = property->values->get_entity_values()[0]; ad_entity->type = "Not-SearchResultAd"; const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(); + auto& property = entities[0]->properties[0]; auto& ad_entity = property->values->get_entity_values()[0]; schema_org::mojom::PropertyPtr extra_property = @@ -118,7 +125,7 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityExtraProperty) { ad_entity->properties.push_back(std::move(extra_property)); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_FALSE(ads.empty()); } } @@ -126,9 +133,10 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityExtraProperty) { TEST(SearchResultAdConvertingTest, NotValidAdEntityPropertySkipped) { constexpr int kSearchResultAdAttributesCount = 12; for (int index = 0; index < kSearchResultAdAttributesCount; ++index) { - blink::mojom::WebPagePtr web_page = CreateTestWebPage(index); + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(index); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } } @@ -136,8 +144,9 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityPropertySkipped) { TEST(SearchResultAdConvertingTest, NotValidAdEntityWrongPropertyType) { { // Skip "data-landing-page". - blink::mojom::WebPagePtr web_page = CreateTestWebPage(0); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(0); + auto& property = entities[0]->properties[0]; auto& ad_entity = property->values->get_entity_values()[0]; schema_org::mojom::PropertyPtr extra_property = @@ -148,14 +157,15 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityWrongPropertyType) { ad_entity->properties.push_back(std::move(extra_property)); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { // Skip "data-rewards-value". - blink::mojom::WebPagePtr web_page = CreateTestWebPage(1); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(1); + auto& property = entities[0]->properties[0]; auto& ad_entity = property->values->get_entity_values()[0]; schema_org::mojom::PropertyPtr extra_property = @@ -166,14 +176,15 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityWrongPropertyType) { ad_entity->properties.push_back(std::move(extra_property)); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { // Skip "data-conversion-observation-window-value". - blink::mojom::WebPagePtr web_page = CreateTestWebPage(2); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(2); + auto& property = entities[0]->properties[0]; auto& ad_entity = property->values->get_entity_values()[0]; schema_org::mojom::PropertyPtr extra_property = @@ -183,14 +194,15 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityWrongPropertyType) { ad_entity->properties.push_back(std::move(extra_property)); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } { // Skip "data-creative-instance-id". - blink::mojom::WebPagePtr web_page = CreateTestWebPage(3); - auto& property = web_page->entities[0]->properties[0]; + std::vector<::schema_org::mojom::EntityPtr> entities = + CreateTestWebPageEntities(3); + auto& property = entities[0]->properties[0]; auto& ad_entity = property->values->get_entity_values()[0]; schema_org::mojom::PropertyPtr extra_property = @@ -200,7 +212,7 @@ TEST(SearchResultAdConvertingTest, NotValidAdEntityWrongPropertyType) { ad_entity->properties.push_back(std::move(extra_property)); const SearchResultAdMap ads = - ConvertWebPageToSearchResultAds(std::move(web_page)); + ConvertWebPageEntitiesToSearchResultAds(entities); EXPECT_TRUE(ads.empty()); } } diff --git a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc index 0ed4301735f7..be6ae526863b 100644 --- a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc +++ b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.cc @@ -11,7 +11,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom.h" namespace brave_ads { @@ -25,21 +24,19 @@ schema_org::mojom::ValuesPtr CreateVectorValuesPtr(int64_t value) { return schema_org::mojom::Values::NewLongValues({value}); } -class TestWebPageConstructor final { +class TestWebPageEntitiesConstructor final { public: - explicit TestWebPageConstructor(int attribute_index_to_skip) + explicit TestWebPageEntitiesConstructor(int attribute_index_to_skip) : attribute_index_to_skip_(attribute_index_to_skip) { - web_page_ = CreateWebPage(); + web_page_entities_ = CreateWebPageEntities(); } - ~TestWebPageConstructor() = default; - TestWebPageConstructor(const TestWebPageConstructor&) = delete; - TestWebPageConstructor& operator=(const TestWebPageConstructor&) = delete; - blink::mojom::WebPagePtr GetTestWebPage() { return std::move(web_page_); } + std::vector<::schema_org::mojom::EntityPtr> GetTestWebPageEntities() { + return std::move(web_page_entities_); + } private: - blink::mojom::WebPagePtr CreateWebPage() { - blink::mojom::WebPagePtr web_page = blink::mojom::WebPage::New(); + std::vector<::schema_org::mojom::EntityPtr> CreateWebPageEntities() { schema_org::mojom::EntityPtr entity = schema_org::mojom::Entity::New(); entity->type = "Product"; schema_org::mojom::PropertyPtr property = @@ -52,9 +49,10 @@ class TestWebPageConstructor final { schema_org::mojom::Values::NewEntityValues(std::move(entity_values)); entity->properties.push_back(std::move(property)); - web_page->entities.push_back(std::move(entity)); + std::vector<::schema_org::mojom::EntityPtr> entities; + entities.push_back(std::move(entity)); - return web_page; + return entities; } template @@ -74,7 +72,7 @@ class TestWebPageConstructor final { } schema_org::mojom::EntityPtr CreateCreativeEntity() { - const char* kSearchResultAdStringAttributes[] = { + constexpr const char* kSearchResultAdStringAttributes[] = { "data-placement-id", "data-creative-set-id", "data-campaign-id", @@ -97,7 +95,7 @@ class TestWebPageConstructor final { "data-conversion-observation-window-value", 1); int index = 0; - for (const auto** it = std::begin(kSearchResultAdStringAttributes); + for (const auto* const* it = std::begin(kSearchResultAdStringAttributes); it != std::end(kSearchResultAdStringAttributes); ++it, ++index) { AddProperty( &entity->properties, *it, @@ -107,16 +105,17 @@ class TestWebPageConstructor final { return entity; } - blink::mojom::WebPagePtr web_page_; + std::vector<::schema_org::mojom::EntityPtr> web_page_entities_; int current_attribute_index_ = 0; int attribute_index_to_skip_ = -1; }; } // namespace -blink::mojom::WebPagePtr CreateTestWebPage(int attribute_index_to_skip) { - TestWebPageConstructor constructor(attribute_index_to_skip); - return constructor.GetTestWebPage(); +std::vector<::schema_org::mojom::EntityPtr> CreateTestWebPageEntities( + int attribute_index_to_skip) { + TestWebPageEntitiesConstructor constructor(attribute_index_to_skip); + return constructor.GetTestWebPageEntities(); } } // namespace brave_ads diff --git a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h index 146a0b7d5846..2a2ea63283df 100644 --- a/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h +++ b/components/brave_ads/core/browser/search_result_ad/test_web_page_util.h @@ -6,14 +6,17 @@ #ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_TEST_WEB_PAGE_UTIL_H_ #define BRAVE_COMPONENTS_BRAVE_ADS_CORE_BROWSER_SEARCH_RESULT_AD_TEST_WEB_PAGE_UTIL_H_ -#include "third_party/blink/public/mojom/document_metadata/document_metadata.mojom-forward.h" +#include + +#include "components/schema_org/common/metadata.mojom.h" namespace brave_ads { constexpr char kTestWebPageCreativeInstanceId[] = "creative_instance_id"; constexpr char kTestWebPageTargetUrl[] = "https://brave.com"; -blink::mojom::WebPagePtr CreateTestWebPage(int attribute_index_to_skip = -1); +std::vector<::schema_org::mojom::EntityPtr> CreateTestWebPageEntities( + int attribute_index_to_skip = -1); } // namespace brave_ads diff --git a/test/BUILD.gn b/test/BUILD.gn index 08cbc4de082b..48e562910e71 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -190,8 +190,8 @@ test("brave_unit_tests") { "//brave/components/brave_adaptive_captcha/test:brave_adaptive_captcha_unit_tests", "//brave/components/brave_ads/browser:test_support", "//brave/components/brave_ads/common", - "//brave/components/brave_ads/content/browser/search_result_ad", - "//brave/components/brave_ads/core/browser/search_result_ad", + "//brave/components/brave_ads/content/browser", + "//brave/components/brave_ads/core/browser", "//brave/components/brave_ads/test:brave_ads_unit_tests", "//brave/components/brave_component_updater/browser", "//brave/components/brave_federated:brave_federated_tests", @@ -277,7 +277,6 @@ test("brave_unit_tests") { "//components/prefs", "//components/prefs:test_support", "//components/query_parser", - "//components/schema_org/common:mojom", "//components/signin/public/base", "//components/signin/public/identity_manager:test_support", "//components/sync_preferences", @@ -831,7 +830,7 @@ test("brave_browser_tests") { "//brave/components/brave_ads/browser", "//brave/components/brave_ads/browser:test_support", "//brave/components/brave_ads/common", - "//brave/components/brave_ads/core/browser/search_result_ad", + "//brave/components/brave_ads/core/browser", "//brave/components/brave_component_updater/browser", "//brave/components/brave_perf_predictor/browser", "//brave/components/brave_perf_predictor/common",