diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni
index da227de40599..9a8ed66f7280 100644
--- a/android/brave_java_sources.gni
+++ b/android/brave_java_sources.gni
@@ -259,11 +259,13 @@ brave_java_sources = [
"../../brave/android/java/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp/NtpUtil.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp/OnBraveNtpListener.java",
+ "../../brave/android/java/org/chromium/chrome/browser/ntp/SponsoredBackgroundWebView.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/NTPBackgroundImagesBridge.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/BackgroundImage.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/ImageCredit.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/NTPImage.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/SponsoredLogo.java",
+ "../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/SponsoredRichMedia.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/SponsoredTab.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/TopSite.java",
"../../brave/android/java/org/chromium/chrome/browser/ntp_background_images/model/Wallpaper.java",
diff --git a/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java b/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java
index 3f7775fa5955..4440d054160e 100644
--- a/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java
+++ b/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java
@@ -31,6 +31,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -39,6 +40,7 @@
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.airbnb.lottie.LottieAnimationView;
@@ -76,6 +78,7 @@
import org.chromium.chrome.browser.logo.LogoCoordinator;
import org.chromium.chrome.browser.ntp_background_images.NTPBackgroundImagesBridge;
import org.chromium.chrome.browser.ntp_background_images.model.NTPImage;
+import org.chromium.chrome.browser.ntp_background_images.model.SponsoredRichMedia;
import org.chromium.chrome.browser.ntp_background_images.model.SponsoredTab;
import org.chromium.chrome.browser.ntp_background_images.model.TopSite;
import org.chromium.chrome.browser.ntp_background_images.model.Wallpaper;
@@ -132,7 +135,13 @@ public class BraveNewTabPageLayout
private Integer mInitialTileNum;
// Own members.
+ private WindowAndroid mWindowAndroid;
+
private ImageView mBgImageView;
+ private SponsoredBackgroundWebView mSponsoredBackgroundWebView;
+ private FrameLayout mBackgroundSponsoredContentView;
+ private SponsoredRichMedia mSponsoredRichMedia;
+
private Profile mProfile;
private SponsoredTab mSponsoredTab;
private boolean mIsTablet;
@@ -441,6 +450,31 @@ private void setNtpRecyclerView(LinearLayoutManager linearLayoutManager) {
}
mPrevVisibleNewsCardPosition = firstNewsFeedPosition() - 1;
+
+ mRecyclerView.addOnItemTouchListener(
+ new OnItemTouchListener() {
+ @Override
+ public boolean onInterceptTouchEvent(
+ RecyclerView recyclerView, MotionEvent event) {
+ final View childView =
+ recyclerView.findChildViewUnder(event.getX(), event.getY());
+ if (childView == null && mSponsoredBackgroundWebView != null) {
+ mSponsoredBackgroundWebView.getView().dispatchTouchEvent(event);
+ }
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView recyclerView, MotionEvent event) {
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(
+ boolean disallowIntercept) {
+ }
+ }
+ );
+
mRecyclerView.addOnScrollListener(
new RecyclerView.OnScrollListener() {
@Override
@@ -931,6 +965,11 @@ public void onConfigurationChanged(Configuration newConfig) {
if (mWallpaper == null) {
mSponsoredTab.setNTPImage(SponsoredImageUtil.getBackgroundImage());
}
+ } else if (ntpImage instanceof SponsoredRichMedia) {
+ mSponsoredRichMedia = (SponsoredRichMedia) ntpImage;
+ if (mSponsoredRichMedia == null) {
+ mSponsoredTab.setNTPImage(SponsoredImageUtil.getBackgroundImage());
+ }
}
super.onConfigurationChanged(newConfig);
showNTPImage(ntpImage);
@@ -1181,6 +1220,8 @@ public void initialize(
tabStripHeightSupplier);
mIsTablet = isTablet;
+ mWindowAndroid = windowAndroid;
+
assert mMvTilesContainerLayout != null : "Something has changed in the upstream!";
@@ -1222,6 +1263,9 @@ private void showNTPImage(NTPImage ntpImage) {
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setBackgroundImage(ntpImage);
+ } else if (ntpImage instanceof SponsoredRichMedia) {
+ final SponsoredRichMedia sponsoredRichMedia = (SponsoredRichMedia) ntpImage;
+ setupSponsoredBackgroundContent(sponsoredRichMedia);
} else if (UserPrefs.get(ProfileManager.getLastUsedRegularProfile())
.getBoolean(BravePref.NEW_TAB_PAGE_SHOW_BACKGROUND_IMAGE)
&& mSponsoredTab != null
@@ -1230,6 +1274,24 @@ private void showNTPImage(NTPImage ntpImage) {
}
}
+ private void createSponsoredBackgroundWebContentsIfNeeded() {
+ if (mSponsoredBackgroundWebView != null) {
+ return;
+ }
+
+ mSponsoredBackgroundWebView = new SponsoredBackgroundWebView(mActivity, mWindowAndroid, mProfile);
+
+ mBackgroundSponsoredContentView = findViewById(R.id.bg_background_view);
+ mBackgroundSponsoredContentView.setVisibility(View.VISIBLE);
+ mBackgroundSponsoredContentView.addView(mSponsoredBackgroundWebView.getView());
+ }
+
+ private void setupSponsoredBackgroundContent(SponsoredRichMedia sponsoredRichMedia) {
+ createSponsoredBackgroundWebContentsIfNeeded();
+
+ mSponsoredBackgroundWebView.loadSponsoredRichMedia(sponsoredRichMedia);
+ }
+
private void setBackgroundImage(NTPImage ntpImage) {
mBgImageView = (ImageView) findViewById(R.id.bg_image_view);
mBgImageView.setScaleType(ImageView.ScaleType.MATRIX);
@@ -1261,6 +1323,11 @@ private void checkAndShowNTPImage(boolean isReset) {
if (mWallpaper == null) {
mSponsoredTab.setNTPImage(SponsoredImageUtil.getBackgroundImage());
}
+ } else if (ntpImage instanceof SponsoredRichMedia) {
+ mSponsoredRichMedia = (SponsoredRichMedia) ntpImage;
+ if (mSponsoredRichMedia == null) {
+ mSponsoredTab.setNTPImage(SponsoredImageUtil.getBackgroundImage());
+ }
}
showNTPImage(ntpImage);
}
diff --git a/android/java/org/chromium/chrome/browser/ntp/SponsoredBackgroundWebView.java b/android/java/org/chromium/chrome/browser/ntp/SponsoredBackgroundWebView.java
new file mode 100644
index 000000000000..eba62d3a8499
--- /dev/null
+++ b/android/java/org/chromium/chrome/browser/ntp/SponsoredBackgroundWebView.java
@@ -0,0 +1,85 @@
+/* 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/. */
+
+package org.chromium.chrome.browser.ntp;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import org.chromium.base.version_info.VersionInfo;
+import org.chromium.chrome.browser.content.WebContentsFactory;
+import org.chromium.chrome.browser.ntp_background_images.model.SponsoredRichMedia;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.embedder_support.view.ContentView;
+import org.chromium.components.thinwebview.ThinWebView;
+import org.chromium.components.thinwebview.ThinWebViewConstraints;
+import org.chromium.components.thinwebview.ThinWebViewFactory;
+import org.chromium.content_public.browser.LoadUrlParams;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.net.NetId;
+import org.chromium.ui.base.IntentRequestTracker;
+import org.chromium.ui.base.ViewAndroidDelegate;
+import org.chromium.ui.base.WindowAndroid;
+
+public class SponsoredBackgroundWebView {
+ private WebContents mSponsoredBackgroundWebContents;
+ private ThinWebView mSponsoredBackgroundWebView;
+
+ private static final String NEW_TAB_TAKEOVER_URL = "chrome://new-tab-takeover";
+ private static final String WALLPAPER_URL = "wallpaperUrl";
+ private static final String CREATIVE_INSTANCE_ID = "creativeInstanceId";
+ private static final String PLACEMENT_ID = "placementId";
+ private static final String TARGET_URL = "targetUrl";
+
+ public SponsoredBackgroundWebView(Activity activity, WindowAndroid windowAndroid, Profile profile) {
+ mSponsoredBackgroundWebContents =
+ WebContentsFactory.createWebContentsWithWarmRenderer(
+ profile,
+ /* initiallyHidden= */ false,
+ /* targetNetwork= */ NetId.INVALID);
+
+ final ContentView webContentView =
+ ContentView.createContentView(activity, mSponsoredBackgroundWebContents);
+ final ViewAndroidDelegate delegate =
+ ViewAndroidDelegate.createBasicDelegate(webContentView);
+ mSponsoredBackgroundWebContents.setDelegates(
+ VersionInfo.getProductVersion(),
+ delegate,
+ webContentView,
+ windowAndroid,
+ WebContents.createDefaultInternalsHolder());
+
+ final IntentRequestTracker intentRequestTracker = windowAndroid.getIntentRequestTracker();
+ mSponsoredBackgroundWebView =
+ ThinWebViewFactory.create(
+ activity, new ThinWebViewConstraints(), intentRequestTracker);
+ mSponsoredBackgroundWebView
+ .getView()
+ .setLayoutParams(
+ new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ mSponsoredBackgroundWebView.attachWebContents(mSponsoredBackgroundWebContents,
+ webContentView,
+ null);
+ }
+
+ public void loadSponsoredRichMedia(SponsoredRichMedia sponsoredRichMedia) {
+ Uri.Builder builder = Uri.parse(NEW_TAB_TAKEOVER_URL).buildUpon();
+ builder.appendQueryParameter(WALLPAPER_URL, sponsoredRichMedia.getWallpaperUrl());
+ builder.appendQueryParameter(CREATIVE_INSTANCE_ID, sponsoredRichMedia.getCreativeInstanceId());
+ builder.appendQueryParameter(PLACEMENT_ID, sponsoredRichMedia.getPlacementId());
+ builder.appendQueryParameter(TARGET_URL, sponsoredRichMedia.getTargetUrl());
+
+ mSponsoredBackgroundWebContents.getNavigationController().loadUrl(
+ new LoadUrlParams(builder.build().toString()));
+ }
+
+ public View getView() {
+ return mSponsoredBackgroundWebView.getView();
+ }
+}
diff --git a/android/java/org/chromium/chrome/browser/ntp_background_images/NTPBackgroundImagesBridge.java b/android/java/org/chromium/chrome/browser/ntp_background_images/NTPBackgroundImagesBridge.java
index c3bba02081fd..5fa86fc36c99 100644
--- a/android/java/org/chromium/chrome/browser/ntp_background_images/NTPBackgroundImagesBridge.java
+++ b/android/java/org/chromium/chrome/browser/ntp_background_images/NTPBackgroundImagesBridge.java
@@ -17,6 +17,7 @@
import org.chromium.chrome.browser.ntp_background_images.model.ImageCredit;
import org.chromium.chrome.browser.ntp_background_images.model.NTPImage;
import org.chromium.chrome.browser.ntp_background_images.model.TopSite;
+import org.chromium.chrome.browser.ntp_background_images.model.SponsoredRichMedia;
import org.chromium.chrome.browser.ntp_background_images.model.Wallpaper;
import org.chromium.chrome.browser.ntp_background_images.util.NewTabPageListener;
import org.chromium.chrome.browser.profiles.Profile;
@@ -155,6 +156,11 @@ public static Wallpaper createBrandedWallpaper(String imagePath, int focalPointX
wallpaperId);
}
+ @CalledByNative
+ public static SponsoredRichMedia createSponsoredRichMedia(String wallpaperUrl, String creativeInstanceId, String placementId, String targetUrl) {
+ return new SponsoredRichMedia(wallpaperUrl, creativeInstanceId, placementId, targetUrl);
+ }
+
@CalledByNative
public void onUpdated() {
for (NTPBackgroundImageServiceObserver observer : mObservers) {
diff --git a/android/java/org/chromium/chrome/browser/ntp_background_images/model/SponsoredRichMedia.java b/android/java/org/chromium/chrome/browser/ntp_background_images/model/SponsoredRichMedia.java
new file mode 100644
index 000000000000..bb3ad370d7ca
--- /dev/null
+++ b/android/java/org/chromium/chrome/browser/ntp_background_images/model/SponsoredRichMedia.java
@@ -0,0 +1,52 @@
+/* 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/. */
+
+package org.chromium.chrome.browser.ntp_background_images.model;
+
+public class SponsoredRichMedia extends NTPImage {
+ private String mWallpaperUrl;
+ private String mCreativeInstanceId;
+ private String mPlacementId;
+ private String mTargetUrl;
+
+ public SponsoredRichMedia(String wallpaperUrl, String creativeInstanceId, String placementId, String targetUrl) {
+ mWallpaperUrl = wallpaperUrl;
+ mCreativeInstanceId = creativeInstanceId;
+ mPlacementId = placementId;
+ mTargetUrl = targetUrl;
+ }
+
+ public String getWallpaperUrl() {
+ return mWallpaperUrl;
+ }
+
+ public void setWallpaperUrl(String wallpaperUrl) {
+ mWallpaperUrl = wallpaperUrl;
+ }
+
+ public String getCreativeInstanceId() {
+ return mCreativeInstanceId;
+ }
+
+ public void setCreativeInstanceId(String creativeInstanceId) {
+ mCreativeInstanceId = creativeInstanceId;
+ }
+
+ public String getPlacementId() {
+ return mPlacementId;
+ }
+
+ public void setPlacementId(String placementId) {
+ mPlacementId = placementId;
+ }
+
+ public String getTargetUrl() {
+ return mTargetUrl;
+ }
+
+ public void setTargetUrl(String targetUrl) {
+ mTargetUrl = targetUrl;
+ }
+}
diff --git a/android/java/org/chromium/chrome/browser/util/TabUtils.java b/android/java/org/chromium/chrome/browser/util/TabUtils.java
index 19c79a8ef61a..7b94896c887e 100644
--- a/android/java/org/chromium/chrome/browser/util/TabUtils.java
+++ b/android/java/org/chromium/chrome/browser/util/TabUtils.java
@@ -46,6 +46,8 @@
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.ui.util.ColorUtils;
+import org.jni_zero.CalledByNative;
+
import java.lang.reflect.Field;
public class TabUtils {
@@ -236,6 +238,7 @@ public static void openUrlInNewTabInBackground(boolean isIncognito, String url)
}
}
+ @CalledByNative
public static void openUrlInSameTab(String url) {
try {
BraveActivity braveActivity = BraveActivity.getBraveActivity();
diff --git a/android/java/res/layout/new_tab_page_layout.xml b/android/java/res/layout/new_tab_page_layout.xml
index 6f9694282743..bdadb6683937 100644
--- a/android/java/res/layout/new_tab_page_layout.xml
+++ b/android/java/res/layout/new_tab_page_layout.xml
@@ -25,6 +25,12 @@
android:layout_height="match_parent"
android:contentDescription="@null"/>
+
+
+
()
.Add();
}
-#endif
+#else
+ registry.ForWebUI()
+ .Add();
+#endif // !BUILDFLAG(IS_ANDROID)
}
std::optional
diff --git a/browser/ntp_background/android/ntp_background_images_bridge.cc b/browser/ntp_background/android/ntp_background_images_bridge.cc
index 720f75b1399f..97299bf9aaa6 100644
--- a/browser/ntp_background/android/ntp_background_images_bridge.cc
+++ b/browser/ntp_background/android/ntp_background_images_bridge.cc
@@ -193,6 +193,42 @@ NTPBackgroundImagesBridge::CreateBrandedWallpaper(
ConvertUTF8ToJavaString(env, wallpaper_id ? *wallpaper_id : ""));
}
+base::android::ScopedJavaLocalRef
+NTPBackgroundImagesBridge::CreateSponsoredRichMedia(
+ const base::Value::Dict& data) {
+ JNIEnv* env = AttachCurrentThread();
+
+ const std::string* wallpaper_url =
+ data.FindString(ntp_background_images::kWallpaperURLKey);
+ if (!wallpaper_url) {
+ return base::android::ScopedJavaLocalRef();
+ }
+
+ const std::string* creative_instance_id =
+ data.FindString(ntp_background_images::kCreativeInstanceIDKey);
+ if (!creative_instance_id) {
+ return base::android::ScopedJavaLocalRef();
+ }
+
+ const std::string* placement_id =
+ data.FindString(ntp_background_images::kWallpaperIDKey);
+ if (!placement_id) {
+ return base::android::ScopedJavaLocalRef();
+ }
+
+ const std::string* target_url = data.FindStringByDottedPath(
+ ntp_background_images::kLogoDestinationURLPath);
+ if (!target_url) {
+ return base::android::ScopedJavaLocalRef();
+ }
+
+ return Java_NTPBackgroundImagesBridge_createSponsoredRichMedia(
+ env, ConvertUTF8ToJavaString(env, *wallpaper_url),
+ ConvertUTF8ToJavaString(env, *creative_instance_id),
+ ConvertUTF8ToJavaString(env, *placement_id),
+ ConvertUTF8ToJavaString(env, *target_url));
+}
+
void NTPBackgroundImagesBridge::GetTopSites(JNIEnv* env,
const JavaParamRef& obj) {
std::vector top_sites =
@@ -257,12 +293,17 @@ NTPBackgroundImagesBridge::GetCurrentWallpaper(
if (!data)
return base::android::ScopedJavaLocalRef();
- bool is_background =
+ const bool is_background =
data->FindBool(ntp_background_images::kIsBackgroundKey).value_or(false);
- if (!is_background) {
- return CreateBrandedWallpaper(*data);
- } else {
+ const std::string* sponsored_rich_media_type =
+ data->FindString(ntp_background_images::kWallpaperTypeKey);
+ if (is_background) {
return CreateWallpaper(*data);
+ } else if (sponsored_rich_media_type &&
+ *sponsored_rich_media_type == "richMedia") {
+ return CreateSponsoredRichMedia(*data);
+ } else {
+ return CreateBrandedWallpaper(*data);
}
}
diff --git a/browser/ntp_background/android/ntp_background_images_bridge.h b/browser/ntp_background/android/ntp_background_images_bridge.h
index e420790e530d..7be54d14b4d9 100644
--- a/browser/ntp_background/android/ntp_background_images_bridge.h
+++ b/browser/ntp_background/android/ntp_background_images_bridge.h
@@ -77,6 +77,8 @@ class NTPBackgroundImagesBridge : public NTPBackgroundImagesService::Observer,
const base::Value::Dict& data);
base::android::ScopedJavaLocalRef CreateBrandedWallpaper(
const base::Value::Dict& data);
+ base::android::ScopedJavaLocalRef CreateSponsoredRichMedia(
+ const base::Value::Dict& data);
raw_ptr profile_ = nullptr;
raw_ptr view_counter_service_ = nullptr;
diff --git a/browser/sources.gni b/browser/sources.gni
index 7f44b6f3c631..18eba7999b7c 100644
--- a/browser/sources.gni
+++ b/browser/sources.gni
@@ -412,6 +412,7 @@ if (is_android) {
"//brave/browser/brave_ads/android",
"//brave/browser/download/android:jni_headers",
"//brave/browser/ntp_background/android",
+ "//brave/browser/ui/webui/new_tab_takeover/android:new_tab_takeover",
"//brave/build/android:jni_headers",
"//brave/components/brave_sync:sync_service_impl_helper",
"//chrome/android:jni_headers",
diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn
index 015abf26273d..6f866c0328af 100644
--- a/browser/ui/BUILD.gn
+++ b/browser/ui/BUILD.gn
@@ -149,7 +149,10 @@ source_set("ui") {
"android/ai_chat/brave_leo_settings_launcher_helper.h",
]
- deps += [ "//brave/build/android:jni_headers" ]
+ deps += [
+ "//brave/browser/ui/webui/new_tab_takeover/android:new_tab_takeover",
+ "//brave/build/android:jni_headers",
+ ]
}
if (enable_ai_rewriter) {
diff --git a/browser/ui/config.gni b/browser/ui/config.gni
index c436a93345c9..586f7e8dacfd 100644
--- a/browser/ui/config.gni
+++ b/browser/ui/config.gni
@@ -13,6 +13,10 @@ if (!is_android) {
"//brave/browser/ui/webui/brave_news_internals",
]
}
+if (is_android) {
+ brave_ui_allow_circular_includes_from +=
+ [ "//brave/browser/ui/webui/new_tab_takeover/android:new_tab_takeover" ]
+}
if (toolkit_views) {
brave_ui_allow_circular_includes_from +=
[ "//brave/browser/ui/views/split_view" ]
diff --git a/browser/ui/webui/brave_web_ui_controller_factory.cc b/browser/ui/webui/brave_web_ui_controller_factory.cc
index aea3eb8d530f..62c8d10820da 100644
--- a/browser/ui/webui/brave_web_ui_controller_factory.cc
+++ b/browser/ui/webui/brave_web_ui_controller_factory.cc
@@ -56,6 +56,7 @@
#if BUILDFLAG(IS_ANDROID)
#include "brave/browser/brave_wallet/brave_wallet_service_factory.h"
#include "brave/browser/ui/webui/brave_wallet/android/android_wallet_page_ui.h"
+#include "brave/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.h"
#include "brave/components/brave_wallet/browser/brave_wallet_service.h"
#include "brave/components/brave_wallet/browser/keyring_service.h"
#endif
@@ -166,6 +167,14 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) {
#if BUILDFLAG(IS_ANDROID)
} else if (url.is_valid() && url.host() == kWalletPageHost) {
return new AndroidWalletPageUI(web_ui, url);
+ } else if (host == kNewTabTakeoverHost) {
+ return new NewTabTakeoverUI(
+ web_ui, url.host(),
+ brave_ads::AdsServiceFactory::GetForProfile(profile),
+ g_browser_process->local_state(),
+ g_brave_browser_process->p3a_service(),
+ g_brave_browser_process->ntp_background_images_service(),
+ profile->GetPrefs());
#endif
#if BUILDFLAG(ENABLE_AI_REWRITER)
} else if (host == kRewriterUIHost) {
@@ -197,6 +206,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
base::FeatureList::IsEnabled(skus::features::kSkusFeature)) ||
#if BUILDFLAG(IS_ANDROID)
(url.is_valid() && url.host_piece() == kWalletPageHost) ||
+ url.host_piece() == kNewTabTakeoverHost ||
#else
(base::FeatureList::IsEnabled(
brave_news::features::kBraveNewsFeedUpdate) &&
diff --git a/browser/ui/webui/new_tab_takeover/android/BUILD.gn b/browser/ui/webui/new_tab_takeover/android/BUILD.gn
new file mode 100644
index 000000000000..df0a70556493
--- /dev/null
+++ b/browser/ui/webui/new_tab_takeover/android/BUILD.gn
@@ -0,0 +1,35 @@
+# 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/.
+
+import("//brave/build/config.gni")
+
+assert(is_android)
+
+source_set("new_tab_takeover") {
+ sources = [
+ "new_tab_takeover_ui.cc",
+ "new_tab_takeover_ui.h",
+ ]
+
+ deps = [
+ "//base",
+ "//brave/browser/ntp_background",
+ "//brave/build/android:jni_headers",
+ "//brave/components/brave_new_tab_ui:new_tab_takeover_generated_resources",
+ "//brave/components/constants",
+ "//brave/components/ntp_background_images/browser",
+ "//brave/components/p3a",
+ "//chrome/browser:browser_public_dependencies",
+ "//content/public/browser",
+ "//content/public/common",
+ "//ui/webui",
+ ]
+
+ public_deps = [
+ "//brave/components/brave_new_tab_ui/new_tab_takeover/mojom",
+ "//brave/components/ntp_background_images/browser/mojom",
+ "//mojo/public/cpp/bindings",
+ ]
+}
diff --git a/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.cc b/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.cc
new file mode 100644
index 000000000000..ea6efa3111ad
--- /dev/null
+++ b/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2025 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "brave/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.h"
+
+#include
+#include
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "brave/browser/ntp_background/ntp_p3a_helper_impl.h"
+#include "brave/browser/ui/webui/brave_webui_source.h"
+#include "brave/build/android/jni_headers/TabUtils_jni.h"
+#include "brave/components/brave_new_tab_ui/new_tab_takeover/grit/new_tab_takeover_generated_map.h"
+#include "brave/components/constants/webui_url_constants.h"
+#include "brave/components/ntp_background_images/browser/ntp_p3a_helper.h"
+#include "brave/components/ntp_background_images/browser/ntp_sponsored_rich_media_ad_event_handler.h"
+#include "components/grit/brave_components_resources.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/url_constants.h"
+
+NewTabTakeoverUI::NewTabTakeoverUI(
+ content::WebUI* const web_ui,
+ const std::string& name,
+ brave_ads::AdsService* ads_service,
+ PrefService* local_state,
+ p3a::P3AService* p3a_service,
+ ntp_background_images::NTPBackgroundImagesService*
+ ntp_background_images_service,
+ PrefService* profile_prefs)
+ : ui::MojoWebUIController(web_ui) {
+ content::WebUIDataSource* source = CreateAndAddWebUIDataSource(
+ web_ui, name, kNewTabTakeoverGenerated, IDR_NEW_TAB_TAKEOVER_HTML);
+
+ web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
+
+ source->OverrideContentSecurityPolicy(
+ network::mojom::CSPDirectiveName::FrameSrc,
+ base::StringPrintf("frame-src %s;", kNTPNewTabTakeoverRichMediaUrl));
+ source->AddString("ntpNewTabTakeoverRichMediaUrl",
+ kNTPNewTabTakeoverRichMediaUrl);
+
+ auto ntp_p3a_helper =
+ std::make_unique(
+ local_state, p3a_service, ntp_background_images_service,
+ profile_prefs);
+
+ rich_media_ad_event_handler_ = std::make_unique<
+ ntp_background_images::NTPSponsoredRichMediaAdEventHandler>(
+ ads_service, std::move(ntp_p3a_helper));
+}
+
+NewTabTakeoverUI::~NewTabTakeoverUI() = default;
+
+void NewTabTakeoverUI::BindInterface(
+ mojo::PendingReceiver
+ pending_receiver) {
+ if (new_tab_takeover_receiver_.is_bound()) {
+ new_tab_takeover_receiver_.reset();
+ }
+
+ new_tab_takeover_receiver_.Bind(std::move(pending_receiver));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NewTabTakeoverUI::SetSponsoredRichMediaAdEventHandler(
+ mojo::PendingReceiver<
+ ntp_background_images::mojom::SponsoredRichMediaAdEventHandler>
+ event_handler) {
+ rich_media_ad_event_handler_->Bind(std::move(event_handler));
+}
+
+void NewTabTakeoverUI::NavigateToUrl(const GURL& url) {
+ Java_TabUtils_openUrlInSameTab(
+ base::android::AttachCurrentThread(),
+ base::android::ConvertUTF8ToJavaString(
+ base::android::AttachCurrentThread(), url.spec()));
+}
+
+WEB_UI_CONTROLLER_TYPE_IMPL(NewTabTakeoverUI)
diff --git a/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.h b/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.h
new file mode 100644
index 000000000000..4505fa83c256
--- /dev/null
+++ b/browser/ui/webui/new_tab_takeover/android/new_tab_takeover_ui.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2025 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_BROWSER_UI_WEBUI_NEW_TAB_TAKEOVER_ANDROID_NEW_TAB_TAKEOVER_UI_H_
+#define BRAVE_BROWSER_UI_WEBUI_NEW_TAB_TAKEOVER_ANDROID_NEW_TAB_TAKEOVER_UI_H_
+
+#include
+#include
+
+#include "brave/components/brave_new_tab_ui/new_tab_takeover/mojom/new_tab_takeover.mojom.h"
+#include "brave/components/ntp_background_images/browser/mojom/ntp_background_images.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "ui/webui/mojo_web_ui_controller.h"
+
+class PrefService;
+
+namespace brave_ads {
+class AdsService;
+} // namespace brave_ads
+
+namespace ntp_background_images {
+class NTPBackgroundImagesService;
+class NTPSponsoredRichMediaAdEventHandler;
+} // namespace ntp_background_images
+
+namespace p3a {
+class P3AService;
+} // namespace p3a
+
+class NewTabTakeoverUI : public ui::MojoWebUIController,
+ public new_tab_takeover::mojom::NewTabTakeover {
+ public:
+ NewTabTakeoverUI(content::WebUI* const web_ui,
+ const std::string& name,
+ brave_ads::AdsService* ads_service,
+ PrefService* local_state,
+ p3a::P3AService* p3a_service,
+ ntp_background_images::NTPBackgroundImagesService*
+ ntp_background_images_service,
+ PrefService* profile_prefs);
+
+ NewTabTakeoverUI(const NewTabTakeoverUI&) = delete;
+ NewTabTakeoverUI& operator=(const NewTabTakeoverUI&) = delete;
+
+ ~NewTabTakeoverUI() override;
+
+ void BindInterface(
+ mojo::PendingReceiver
+ pending_receiver);
+
+ private:
+ // new_tab_takeover::mojom::NewTabTakeover:
+ void SetSponsoredRichMediaAdEventHandler(
+ mojo::PendingReceiver<
+ ntp_background_images::mojom::SponsoredRichMediaAdEventHandler>
+ event_handler) override;
+ void NavigateToUrl(const GURL& url) override;
+
+ mojo::Receiver
+ new_tab_takeover_receiver_{this};
+
+ std::unique_ptr
+ rich_media_ad_event_handler_;
+
+ WEB_UI_CONTROLLER_TYPE_DECL();
+};
+
+#endif // BRAVE_BROWSER_UI_WEBUI_NEW_TAB_TAKEOVER_ANDROID_NEW_TAB_TAKEOVER_UI_H_
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn
index 3f98c4155052..d7b9f1a445e4 100644
--- a/build/android/BUILD.gn
+++ b/build/android/BUILD.gn
@@ -240,6 +240,7 @@ generate_jni("jni_headers") {
"//brave/android/java/org/chromium/chrome/browser/signin/BraveSigninManager.java",
"//brave/android/java/org/chromium/chrome/browser/speedreader/BraveSpeedReaderUtils.java",
"//brave/android/java/org/chromium/chrome/browser/sync/BraveSyncDevices.java",
+ "//brave/android/java/org/chromium/chrome/browser/util/TabUtils.java",
"//brave/android/java/org/chromium/chrome/browser/vpn/BraveVpnNativeWorker.java",
"//brave/android/java/org/chromium/chrome/browser/vpn/BraveVpnServiceFactoryAndroid.java",
"//brave/android/java/org/chromium/chrome/browser/webcompat_reporter/WebcompatReporterServiceFactory.java",
diff --git a/chromium_src/chrome/common/webui_url_constants.cc b/chromium_src/chrome/common/webui_url_constants.cc
index abe7946d8a11..a560046399e6 100644
--- a/chromium_src/chrome/common/webui_url_constants.cc
+++ b/chromium_src/chrome/common/webui_url_constants.cc
@@ -9,7 +9,8 @@
#define kChromeUIAttributionInternalsHost \
kChromeUIAttributionInternalsHost, kAdblockHost, kAdblockInternalsHost, \
kRewardsPageHost, kRewardsInternalsHost, kWelcomeHost, kWalletPageHost, \
- kTorInternalsHost, kSkusInternalsHost, kAdsInternalsHost
+ kTorInternalsHost, kSkusInternalsHost, kAdsInternalsHost, \
+ kNewTabTakeoverHost
#include "src/chrome/common/webui_url_constants.cc"
diff --git a/components/brave_new_tab_ui/BUILD.gn b/components/brave_new_tab_ui/BUILD.gn
index 04f7f5c04bb4..6e586ef586ac 100644
--- a/components/brave_new_tab_ui/BUILD.gn
+++ b/components/brave_new_tab_ui/BUILD.gn
@@ -43,3 +43,24 @@ mojom("mojom") {
enabled_features = [ "enable_brave_vpn" ]
}
}
+
+transpile_web_ui("new_tab_takeover_ui") {
+ resource_name = "new_tab_takeover"
+ entry_points = [ [
+ "new_tab_takeover",
+ rebase_path("new_tab_takeover/new_tab_takeover.tsx"),
+ ] ]
+ public_deps = [
+ "//brave/components/brave_ads/core/mojom:mojom_js",
+ "//brave/components/brave_new_tab_ui/new_tab_takeover/mojom:mojom_js",
+ "//brave/components/ntp_background_images/browser/mojom:mojom_js",
+ "//mojo/public/mojom/base",
+ ]
+}
+
+pack_web_resources("new_tab_takeover_generated_resources") {
+ resource_name = "new_tab_takeover"
+ output_dir =
+ "$root_gen_dir/brave/components/brave_new_tab_ui/new_tab_takeover"
+ deps = [ ":new_tab_takeover_ui" ]
+}
diff --git a/components/brave_new_tab_ui/new_tab_takeover/App.tsx b/components/brave_new_tab_ui/new_tab_takeover/App.tsx
new file mode 100644
index 000000000000..f2f35458b072
--- /dev/null
+++ b/components/brave_new_tab_ui/new_tab_takeover/App.tsx
@@ -0,0 +1,78 @@
+// 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/.
+
+import * as React from 'react';
+import * as NTPBackgroundMediaMojom from 'gen/brave/components/ntp_background_images/browser/mojom/ntp_background_images.mojom.m.js'
+import * as NewTabTakeoverMojom from 'gen/brave/components/brave_new_tab_ui/new_tab_takeover/mojom/new_tab_takeover.mojom.m.js'
+import * as BraveAdsMojom from 'gen/brave/components/brave_ads/core/mojom/brave_ads.mojom.m.js'
+import { Url } from 'gen/url/mojom/url.mojom.m.js'
+
+import {
+ SponsoredRichMediaBackgroundInfo, SponsoredRichMediaBackground
+} from '../containers/newTab/sponsored_rich_media_background'
+
+export default function App(props: React.PropsWithChildren) {
+ const [sponsoredRichMediaBackgroundInfo, setSponsoredRichMediaBackgroundInfo] = React.useState(null)
+ const [sponsoredRichMediaAdEventHandler, setSponsoredRichMediaAdEventHandler] = React.useState(null)
+ const [newTabTakeover, setNewTabTakeover] = React.useState(null)
+ const [richMediaHasLoaded, setRichMediaHasLoaded] = React.useState(false)
+
+ React.useEffect(() => {
+ const params = new URLSearchParams(window.location.search)
+ const wallpaperUrl = params.get('wallpaperUrl')
+ const creativeInstanceId = params.get('creativeInstanceId')
+ const placementId = params.get('placementId')
+ const targetUrl = params.get('targetUrl')
+
+ if (!wallpaperUrl || !creativeInstanceId || !placementId) {
+ return
+ }
+
+ const sponsoredRichMediaBackgroundInfo: SponsoredRichMediaBackgroundInfo = {
+ url: wallpaperUrl,
+ creativeInstanceId: creativeInstanceId,
+ placementId: placementId,
+ targetUrl: targetUrl ?? ''
+ }
+ setSponsoredRichMediaBackgroundInfo(sponsoredRichMediaBackgroundInfo)
+
+ const newTabTakeover = NewTabTakeoverMojom.NewTabTakeover.getRemote();
+ setNewTabTakeover(newTabTakeover)
+
+ const sponsoredRichMediaAdEventHandler = new NTPBackgroundMediaMojom.SponsoredRichMediaAdEventHandlerRemote()
+ newTabTakeover.setSponsoredRichMediaAdEventHandler(sponsoredRichMediaAdEventHandler.$.bindNewPipeAndPassReceiver())
+ setSponsoredRichMediaAdEventHandler(sponsoredRichMediaAdEventHandler)
+
+ return () => {
+ setSponsoredRichMediaBackgroundInfo(null)
+ setNewTabTakeover(null)
+ setSponsoredRichMediaAdEventHandler(null)
+ }
+ }, [])
+
+ if (!sponsoredRichMediaBackgroundInfo || !sponsoredRichMediaAdEventHandler || !newTabTakeover) {
+ return null
+ }
+
+ return (
+ { setRichMediaHasLoaded(true) }}
+ onEventReported={(adEventType) => {
+ sponsoredRichMediaAdEventHandler.reportRichMediaAdEvent(
+ sponsoredRichMediaBackgroundInfo.creativeInstanceId,
+ sponsoredRichMediaBackgroundInfo.placementId,
+ adEventType)
+
+ if (adEventType === BraveAdsMojom.NewTabPageAdEventType.kClicked) {
+ const mojomUrl = new Url()
+ mojomUrl.url = sponsoredRichMediaBackgroundInfo.targetUrl
+ newTabTakeover.navigateToUrl(mojomUrl)
+ }
+ }}
+ />
+ )
+}
diff --git a/components/brave_new_tab_ui/new_tab_takeover/mojom/BUILD.gn b/components/brave_new_tab_ui/new_tab_takeover/mojom/BUILD.gn
new file mode 100644
index 000000000000..1555904b59ff
--- /dev/null
+++ b/components/brave_new_tab_ui/new_tab_takeover/mojom/BUILD.gn
@@ -0,0 +1,16 @@
+# 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/.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+ generate_java = true
+ sources = [ "new_tab_takeover.mojom" ]
+
+ public_deps = [
+ "//brave/components/ntp_background_images/browser/mojom",
+ "//mojo/public/mojom/base",
+ ]
+}
diff --git a/components/brave_new_tab_ui/new_tab_takeover/mojom/new_tab_takeover.mojom b/components/brave_new_tab_ui/new_tab_takeover/mojom/new_tab_takeover.mojom
new file mode 100644
index 000000000000..52b222d195b2
--- /dev/null
+++ b/components/brave_new_tab_ui/new_tab_takeover/mojom/new_tab_takeover.mojom
@@ -0,0 +1,16 @@
+// 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/.
+
+module new_tab_takeover.mojom;
+
+import "url/mojom/url.mojom";
+import "brave/components/ntp_background_images/browser/mojom/ntp_background_images.mojom";
+
+interface NewTabTakeover {
+ SetSponsoredRichMediaAdEventHandler(
+ pending_receiver event_handler);
+
+ NavigateToUrl(url.mojom.Url url);
+};
diff --git a/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover.html b/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover.html
new file mode 100644
index 000000000000..8c628d49814d
--- /dev/null
+++ b/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ New Tab Takeover Page
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover.tsx b/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover.tsx
new file mode 100644
index 000000000000..9052936991a9
--- /dev/null
+++ b/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover.tsx
@@ -0,0 +1,15 @@
+// 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/.
+
+import * as React from 'react'
+import { createRoot } from 'react-dom/client'
+import { setIconBasePath } from '@brave/leo/react/icon'
+import App from './App'
+
+setIconBasePath('//resources/brave-icons')
+
+createRoot(document.querySelector('#root')!).render(
+
+)
diff --git a/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover_resources.grdp b/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover_resources.grdp
new file mode 100644
index 000000000000..5f224dc39e11
--- /dev/null
+++ b/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover_resources.grdp
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/components/constants/webui_url_constants.h b/components/constants/webui_url_constants.h
index 69ed9e31e814..8e78ad02d0a3 100644
--- a/components/constants/webui_url_constants.h
+++ b/components/constants/webui_url_constants.h
@@ -16,6 +16,7 @@ inline constexpr char kAdblockInternalsHost[] = "adblock-internals";
inline constexpr char kAdblockJS[] = "brave_adblock.js";
inline constexpr char kSkusInternalsHost[] = "skus-internals";
inline constexpr char kAdsInternalsHost[] = "ads-internals";
+inline constexpr char kNewTabTakeoverHost[] = "new-tab-takeover";
inline constexpr char kWebcompatReporterHost[] = "webcompat";
inline constexpr char kRewardsPageHost[] = "rewards";
inline constexpr char kRewardsPageURL[] = "chrome://rewards/";
@@ -100,6 +101,9 @@ inline constexpr char kNTPNewTabTakeoverRichMediaUrl[] =
inline constexpr char kBraveUINewTabURL[] = "chrome://newtab/";
+inline constexpr char kBraveUINewTabTakeoverURL[] =
+ "chrome://new-tab-takeover/";
+
// Hosts that are allowed to be installed as PWAs, which is usually
// a blocked action for WebUIs. In Chromium, the "password-manager" host
// is already allowed.
diff --git a/components/ntp_background_images/browser/ntp_sponsored_rich_media_source.cc b/components/ntp_background_images/browser/ntp_sponsored_rich_media_source.cc
index ca93782d73ba..05d9302487a4 100644
--- a/components/ntp_background_images/browser/ntp_sponsored_rich_media_source.cc
+++ b/components/ntp_background_images/browser/ntp_sponsored_rich_media_source.cc
@@ -12,6 +12,7 @@
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/strings/stringprintf.h"
#include "base/task/thread_pool.h"
#include "brave/components/constants/webui_url_constants.h"
#include "brave/components/ntp_background_images/browser/ntp_background_images_service.h"
@@ -98,7 +99,8 @@ std::string NTPSponsoredRichMediaSource::GetContentSecurityPolicy(
network::mojom::CSPDirectiveName directive) {
switch (directive) {
case network::mojom::CSPDirectiveName::FrameAncestors:
- return std::string("frame-ancestors ") + kBraveUINewTabURL + ";";
+ return base::StringPrintf("frame-ancestors %s %s;", kBraveUINewTabURL,
+ kBraveUINewTabTakeoverURL);
case network::mojom::CSPDirectiveName::Sandbox:
return "sandbox allow-scripts;";
case network::mojom::CSPDirectiveName::DefaultSrc:
diff --git a/components/ntp_background_images/browser/ntp_sponsored_rich_media_source_unittest.cc b/components/ntp_background_images/browser/ntp_sponsored_rich_media_source_unittest.cc
index efe338b59842..e54fcd720897 100644
--- a/components/ntp_background_images/browser/ntp_sponsored_rich_media_source_unittest.cc
+++ b/components/ntp_background_images/browser/ntp_sponsored_rich_media_source_unittest.cc
@@ -143,8 +143,9 @@ TEST_F(NTPSponsoredRichMediaSourceTest, GetContentSecurityPolicy) {
const auto directive = static_cast(i);
switch (directive) {
case network::mojom::CSPDirectiveName::FrameAncestors: {
- EXPECT_EQ("frame-ancestors chrome://newtab/;",
- url_data_source()->GetContentSecurityPolicy(directive));
+ EXPECT_EQ(
+ "frame-ancestors chrome://newtab/ chrome://new-tab-takeover/;",
+ url_data_source()->GetContentSecurityPolicy(directive));
break;
}
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn
index 9d4b0d4b2e75..263e3842c1b0 100644
--- a/components/resources/BUILD.gn
+++ b/components/resources/BUILD.gn
@@ -69,6 +69,11 @@ repack("resources") {
"$root_gen_dir/components/brave_components_static.pak",
]
+ if (is_android) {
+ deps += [ "//brave/components/brave_new_tab_ui:new_tab_takeover_generated_resources" ]
+ sources += [ "$root_gen_dir/brave/components/brave_new_tab_ui/new_tab_takeover/new_tab_takeover_generated.pak" ]
+ }
+
if (!is_ios) {
deps += [
"//brave/components/brave_adblock_ui:generated_resources",
diff --git a/components/resources/brave_components_resources.grd b/components/resources/brave_components_resources.grd
index 71509dd54ba6..7022c227a93a 100644
--- a/components/resources/brave_components_resources.grd
+++ b/components/resources/brave_components_resources.grd
@@ -104,6 +104,10 @@
+
+
+
+
diff --git a/resources/resource_ids.spec b/resources/resource_ids.spec
index 58e0454fa138..d24c52c73520 100644
--- a/resources/resource_ids.spec
+++ b/resources/resource_ids.spec
@@ -241,6 +241,10 @@
"META": {"sizes": {"includes": [10]}},
"includes": [34770],
},
+ "<(SHARED_INTERMEDIATE_DIR)/brave/web-ui-new_tab_takeover/new_tab_takeover.grd": {
+ "META": {"sizes": {"includes": [10]}},
+ "includes": [34780],
+ },
# WARNING: The upstream ChromeOS/Ash strings currently run through 36930. We
# must be careful not to exceed that maximum when adding new strings here.
}