Skip to content

Commit

Permalink
[ads] RichNTT: Desktop
Browse files Browse the repository at this point in the history
  • Loading branch information
tmancey committed Feb 7, 2025
1 parent aa7443a commit b919192
Show file tree
Hide file tree
Showing 52 changed files with 2,632 additions and 445 deletions.
41 changes: 28 additions & 13 deletions browser/ntp_background/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -89,25 +89,40 @@ source_set("unit_tests") {
}
}

if (enable_custom_background) {
source_set("browser_tests") {
testonly = true
source_set("browser_tests") {
testonly = true

defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]

sources = [ "custom_background_file_manager_browsertest.cc" ]
sources = [
"ntp_sponsored_rich_media_browsertest.cc",
"ntp_sponsored_rich_media_with_csp_violation_browsertest.cc",
]

deps = [
":ntp_background",
"//base",
"//base/test:test_support",
"//brave/components/constants",
deps = [
":ntp_background",
"//base",
"//brave/components/constants",
"//brave/components/ntp_background_images/browser",
"//brave/components/ntp_background_images/browser:test_support",
"//chrome/browser/ui",
"//chrome/test:test_support",
"//content/test:test_support",
]

data = [
"//brave/test/data/brave_ads/component/rich_media",
"//brave/test/data/brave_ads/component/rich_media_with_csp_violation",
]

if (enable_custom_background) {
sources += [ "custom_background_file_manager_browsertest.cc" ]

deps += [
"//chrome/browser/profiles:profile",
"//chrome/browser/ui",
"//chrome/test:test_support_ui",
"//content/test:test_support",
]

data = [ "//brave/test/data/ntp_background/background.jpg" ]
data += [ "//brave/test/data/ntp_background/background.jpg" ]
}
}
81 changes: 81 additions & 0 deletions browser/ntp_background/ntp_sponsored_rich_media_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* Copyright (c) 2025 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/path_service.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/components/constants/brave_paths.h"
#include "brave/components/ntp_background_images/browser/ntp_background_images_service.h"
#include "brave/components/ntp_background_images/browser/ntp_background_images_service_waiter.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "chrome/test/base/platform_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace ntp_background_images {

namespace {

constexpr char kRichMediaUrl[] =
R"(chrome-untrusted://rich-media/aa0b561e-9eed-4aaa-8999-5627bc6b14fd/index.html)";

} // namespace

class NTPSponsoredRichMediaBrowserTest : public PlatformBrowserTest {
protected:
void SetUpOnMainThread() override {
PlatformBrowserTest::SetUpOnMainThread();

const base::FilePath test_data_file_path =
base::PathService::CheckedGet(brave::DIR_TEST_DATA);

const base::FilePath component_file_path =
test_data_file_path.AppendASCII("ntp_background_images")
.AppendASCII("components")
.AppendASCII("rich_media");

NTPBackgroundImagesService* const ntp_background_images_service =
g_brave_browser_process->ntp_background_images_service();
ASSERT_TRUE(ntp_background_images_service);

NTPBackgroundImagesServiceWaiter waiter(*ntp_background_images_service);
ntp_background_images_service->OnSponsoredComponentReady(
/*is_super_referral=*/false, component_file_path);
waiter.WaitForOnSponsoredImagesUpdated();
}

content::WebContents* GetActiveWebContents() {
return chrome_test_utils::GetActiveWebContents(this);
}
};

IN_PROC_BROWSER_TEST_F(NTPSponsoredRichMediaBrowserTest,
LoadResourceAndClickButton) {
content::WebContentsConsoleObserver console_observer(GetActiveWebContents());
console_observer.SetFilter(base::BindRepeating(
[](const content::WebContentsConsoleObserver::Message& message) {
return message.log_level == blink::mojom::ConsoleMessageLevel::kError;
}));
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kRichMediaUrl)));
EXPECT_TRUE(console_observer.messages().empty());

ASSERT_TRUE(
content::ExecJs(GetActiveWebContents(),
"document.querySelector('.button-box').click();"));
content::EvalJsResult result =
content::EvalJs(GetActiveWebContents(),
"document.querySelector('.button-box').textContent;");
EXPECT_EQ(result.ExtractString(), "Clicked");
}

} // namespace ntp_background_images
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* Copyright (c) 2025 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/components/constants/brave_paths.h"
#include "brave/components/ntp_background_images/browser/ntp_background_images_service.h"
#include "brave/components/ntp_background_images/browser/ntp_background_images_service_waiter.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "chrome/test/base/platform_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace ntp_background_images {

namespace {

constexpr char kRichMediaUrl[] =
R"(chrome-untrusted://rich-media/aa0b561e-9eed-4aaa-8999-5627bc6b14fd/index.html)";

} // namespace

class NTPSponsoredRichMediaWithCSPViolationBrowserTest
: public PlatformBrowserTest {
protected:
void SetUpOnMainThread() override {
PlatformBrowserTest::SetUpOnMainThread();

const base::FilePath test_data_file_path =
base::PathService::CheckedGet(brave::DIR_TEST_DATA);

const base::FilePath component_file_path =
test_data_file_path.AppendASCII("ntp_background_images")
.AppendASCII("components")
.AppendASCII("rich_media_with_csp_violation");

NTPBackgroundImagesService* const ntp_background_images_service =
g_brave_browser_process->ntp_background_images_service();
ASSERT_TRUE(ntp_background_images_service);

NTPBackgroundImagesServiceWaiter waiter(*ntp_background_images_service);
ntp_background_images_service->OnSponsoredComponentReady(
/*is_super_referral=*/false, component_file_path);
waiter.WaitForOnSponsoredImagesUpdated();
}

content::WebContents* GetActiveWebContents() {
return chrome_test_utils::GetActiveWebContents(this);
}

void NavigateToUrlAndVerifyExpectation(
const std::string& console_observer_pattern) {
content::WebContentsConsoleObserver console_observer(
GetActiveWebContents());
console_observer.SetPattern(console_observer_pattern);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(kRichMediaUrl)));
EXPECT_TRUE(console_observer.Wait());
}
};

IN_PROC_BROWSER_TEST_F(NTPSponsoredRichMediaWithCSPViolationBrowserTest,
DoNotLoadLocalResource) {
NavigateToUrlAndVerifyExpectation(
"Not allowed to load local resource: chrome://csp-violation/script.js");
}

IN_PROC_BROWSER_TEST_F(NTPSponsoredRichMediaWithCSPViolationBrowserTest,
DoNotLoadLocalResourceWithDifferentOrigin) {
NavigateToUrlAndVerifyExpectation(
R"(Refused to load the stylesheet )"
R"('chrome-untrusted://csp-violation/styles.css' because it violates the )"
R"(following Content Security Policy directive: "style-src 'self'".*)");
}

IN_PROC_BROWSER_TEST_F(NTPSponsoredRichMediaWithCSPViolationBrowserTest,
DoNotLoadRemoteResource) {
NavigateToUrlAndVerifyExpectation(
R"(Refused to load the image 'https://csp-violation.com/background.jpg' )"
R"(because it violates the following Content Security Policy directive: )"
R"("img-src 'self'".*)");
}

} // namespace ntp_background_images
4 changes: 4 additions & 0 deletions browser/ntp_background/view_counter_service_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "brave/components/ntp_background_images/browser/ntp_background_images_service.h"
#include "brave/components/ntp_background_images/browser/ntp_background_images_source.h"
#include "brave/components/ntp_background_images/browser/ntp_sponsored_images_source.h"
#include "brave/components/ntp_background_images/browser/ntp_sponsored_rich_media_source.h"
#include "brave/components/ntp_background_images/browser/view_counter_service.h"
#include "brave/components/ntp_background_images/buildflags/buildflags.h"
#include "chrome/browser/browser_process.h"
Expand Down Expand Up @@ -79,6 +80,9 @@ ViewCounterServiceFactory::BuildServiceInstanceForBrowserContext(
browser_context, std::make_unique<NTPBackgroundImagesSource>(service));
content::URLDataSource::Add(
browser_context, std::make_unique<NTPSponsoredImagesSource>(service));
content::URLDataSource::Add(
browser_context,
std::make_unique<NTPSponsoredRichMediaSource>(service->AsWeakPtr()));

std::unique_ptr<NTPP3AHelperImpl> ntp_p3a_helper;
if (g_brave_browser_process->p3a_service() != nullptr) {
Expand Down
41 changes: 40 additions & 1 deletion browser/ui/webui/new_tab_page/brave_new_tab_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@

#include "base/check.h"
#include "base/feature_list.h"
#include "base/strings/stringprintf.h"
#include "brave/browser/brave_ads/ads_service_factory.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/browser/brave_news/brave_news_controller_factory.h"
#include "brave/browser/misc_metrics/process_misc_metrics.h"
#include "brave/browser/new_tab/new_tab_shows_options.h"
#include "brave/browser/ntp_background/brave_ntp_custom_background_service_factory.h"
#include "brave/browser/ntp_background/ntp_p3a_helper_impl.h"
#include "brave/browser/ui/brave_ui_features.h"
#include "brave/browser/ui/webui/brave_webui_source.h"
#include "brave/browser/ui/webui/new_tab_page/brave_new_tab_message_handler.h"
Expand All @@ -23,9 +26,12 @@
#include "brave/components/brave_new_tab/resources/grit/brave_new_tab_generated_map.h"
#include "brave/components/brave_news/browser/brave_news_controller.h"
#include "brave/components/brave_news/common/features.h"
#include "brave/components/constants/webui_url_constants.h"
#include "brave/components/l10n/common/localization_util.h"
#include "brave/components/misc_metrics/new_tab_metrics.h"
#include "brave/components/ntp_background_images/browser/ntp_custom_images_source.h"
#include "brave/components/ntp_background_images/browser/ntp_sponsored_rich_media_ad_event_handler.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/themes/theme_syncable_service.h"
Expand All @@ -36,6 +42,7 @@
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/url_constants.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/resources/cr_components/searchbox/searchbox.mojom.h"

Expand Down Expand Up @@ -76,6 +83,8 @@ BraveNewTabUI::BraveNewTabUI(content::WebUI* web_ui, const std::string& name)
content::WebUIDataSource* source = CreateAndAddWebUIDataSource(
web_ui, name, kBraveNewTabGenerated, IDR_BRAVE_NEW_TAB_HTML);

web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);

AddBackgroundColorToSource(source, web_contents);

// Lottie animations tick on a worker thread and requires the document CSP to
Expand Down Expand Up @@ -127,6 +136,10 @@ BraveNewTabUI::BraveNewTabUI(content::WebUI* web_ui, const std::string& name)
std::make_unique<NTPCustomImagesSource>(
ntp_custom_background_images_service));
}

source->OverrideContentSecurityPolicy(
network::mojom::CSPDirectiveName::FrameSrc,
base::StringPrintf("frame-src %s;", kNTPSponsoredRichMediaUrl));
}

BraveNewTabUI::~BraveNewTabUI() = default;
Expand Down Expand Up @@ -182,14 +195,40 @@ void BraveNewTabUI::CreatePageHandler(
mojo::PendingReceiver<brave_new_tab_page::mojom::PageHandler>
pending_page_handler,
mojo::PendingReceiver<brave_new_tab_page::mojom::NewTabMetrics>
pending_new_tab_metrics) {
pending_new_tab_metrics,
mojo::PendingReceiver<
ntp_background_images::mojom::SponsoredRichMediaAdEventHandler>
pending_rich_media_ad_event_handler) {
DCHECK(pending_page.is_valid());
Profile* profile = Profile::FromWebUI(web_ui());
page_handler_ = std::make_unique<BraveNewTabPageHandler>(
std::move(pending_page_handler), std::move(pending_page), profile,
web_ui()->GetWebContents());
g_brave_browser_process->process_misc_metrics()->new_tab_metrics()->Bind(
std::move(pending_new_tab_metrics));
CreateSponsoredRichMediaAdEventHandler(
profile, std::move(pending_rich_media_ad_event_handler));
}

void BraveNewTabUI::CreateSponsoredRichMediaAdEventHandler(
Profile* profile,
mojo::PendingReceiver<
ntp_background_images::mojom::SponsoredRichMediaAdEventHandler>
pending_rich_media_ad_event_handler) {
std::unique_ptr<ntp_background_images::NTPP3AHelperImpl> ntp_p3a_helper;
if (g_brave_browser_process->p3a_service() != nullptr) {
ntp_p3a_helper = std::make_unique<ntp_background_images::NTPP3AHelperImpl>(
g_browser_process->local_state(),
g_brave_browser_process->p3a_service(),
g_brave_browser_process->ntp_background_images_service(),
profile->GetPrefs());
}

rich_media_ad_event_handler_ = std::make_unique<
ntp_background_images::NTPSponsoredRichMediaAdEventHandler>(
brave_ads::AdsServiceFactory::GetForProfile(profile),
std::move(ntp_p3a_helper),
std::move(pending_rich_media_ad_event_handler));
}

WEB_UI_CONTROLLER_TYPE_IMPL(BraveNewTabUI)
18 changes: 17 additions & 1 deletion browser/ui/webui/new_tab_page/brave_new_tab_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ namespace brave_news {
class BraveNewsController;
} // namespace brave_news

namespace ntp_background_images {
class NTPSponsoredRichMediaAdEventHandler;
} // namespace ntp_background_images

class BraveNewTabPageHandler;
class Profile;

class BraveNewTabUI : public ui::MojoWebUIController,
public brave_new_tab_page::mojom::PageHandlerFactory {
Expand Down Expand Up @@ -62,12 +67,23 @@ class BraveNewTabUI : public ui::MojoWebUIController,
mojo::PendingReceiver<brave_new_tab_page::mojom::PageHandler>
pending_page_handler,
mojo::PendingReceiver<brave_new_tab_page::mojom::NewTabMetrics>
pending_new_tab_metrics) override;
pending_new_tab_metrics,
mojo::PendingReceiver<
ntp_background_images::mojom::SponsoredRichMediaAdEventHandler>
pending_rich_media_ad_event_handler) override;

void CreateSponsoredRichMediaAdEventHandler(
Profile* profile,
mojo::PendingReceiver<
ntp_background_images::mojom::SponsoredRichMediaAdEventHandler>
pending_rich_media_ad_event_handler);

std::unique_ptr<BraveNewTabPageHandler> page_handler_;
std::unique_ptr<RealboxHandler> realbox_handler_;
mojo::Receiver<brave_new_tab_page::mojom::PageHandlerFactory>
page_factory_receiver_;
std::unique_ptr<ntp_background_images::NTPSponsoredRichMediaAdEventHandler>
rich_media_ad_event_handler_;

WEB_UI_CONTROLLER_TYPE_DECL();
};
Expand Down
1 change: 1 addition & 0 deletions components/brave_new_tab_ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mojom("mojom") {
sources = [ "brave_new_tab_page.mojom" ]
public_deps = [
"//brave/components/brave_vpn/common/mojom",
"//brave/components/ntp_background_images/browser/mojom",
"//url/mojom:url_mojom_gurl",
]
if (enable_brave_vpn) {
Expand Down
Loading

0 comments on commit b919192

Please # to comment.