Skip to content

Commit

Permalink
[ads] RichNTT: Android
Browse files Browse the repository at this point in the history
  • Loading branch information
aseren committed Feb 20, 2025
1 parent 5f96b0c commit 0ef68e4
Show file tree
Hide file tree
Showing 30 changed files with 640 additions and 8 deletions.
1 change: 1 addition & 0 deletions android/brave_java_sources.gni
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ brave_java_sources = [
"../../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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

import android.net.Uri;
import android.widget.FrameLayout;
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
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.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;

public class BraveNewTabPageLayout
extends NewTabPageLayout implements ConnectionErrorHandler, OnBraveNtpListener {
private static final String TAG = "BraveNewTabPage";
Expand All @@ -132,7 +148,14 @@ public class BraveNewTabPageLayout
private Integer mInitialTileNum;

// Own members.
private WindowAndroid mWindowAndroid;

private ImageView mBgImageView;
private WebContents mSponsoredBackgroundWebContents;
private ThinWebView mSponsoredBackgroundWebView;
private FrameLayout mBackgroundSponsoredContentView;
private SponsoredRichMedia mSponsoredRichMedia;

private Profile mProfile;
private SponsoredTab mSponsoredTab;
private boolean mIsTablet;
Expand Down Expand Up @@ -441,6 +464,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
Expand Down Expand Up @@ -931,6 +979,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);
Expand Down Expand Up @@ -1181,6 +1234,8 @@ public void initialize(
tabStripHeightSupplier);

mIsTablet = isTablet;
mWindowAndroid = windowAndroid;


assert mMvTilesContainerLayout != null : "Something has changed in the upstream!";

Expand Down Expand Up @@ -1222,6 +1277,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
Expand All @@ -1230,6 +1288,61 @@ private void showNTPImage(NTPImage ntpImage) {
}
}

private void createSponsoredBackgroundWebContentsIfNeeded() {
if (mSponsoredBackgroundWebContents != null) {
return;
}

mSponsoredBackgroundWebContents =
WebContentsFactory.createWebContentsWithWarmRenderer(
mProfile,
/* initiallyHidden= */ false,
/* targetNetwork= */ NetId.INVALID);

final ContentView webContentView =
ContentView.createContentView(mActivity, mSponsoredBackgroundWebContents);
final ViewAndroidDelegate delegate =
ViewAndroidDelegate.createBasicDelegate(webContentView);
mSponsoredBackgroundWebContents.setDelegates(
VersionInfo.getProductVersion(),
delegate,
webContentView,
mWindowAndroid,
WebContents.createDefaultInternalsHolder());

final IntentRequestTracker intentRequestTracker = mWindowAndroid.getIntentRequestTracker();
mSponsoredBackgroundWebView =
ThinWebViewFactory.create(
mActivity, new ThinWebViewConstraints(), intentRequestTracker);
mSponsoredBackgroundWebView
.getView()
.setLayoutParams(
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mSponsoredBackgroundWebView.attachWebContents(mSponsoredBackgroundWebContents,
webContentView,
null);

mBackgroundSponsoredContentView = findViewById(R.id.bg_background_view);
mBackgroundSponsoredContentView.setVisibility(View.VISIBLE);
mBackgroundSponsoredContentView.addView(mSponsoredBackgroundWebView.getView());
}

private void setupSponsoredBackgroundContent(SponsoredRichMedia sponsoredRichMedia) {
createSponsoredBackgroundWebContentsIfNeeded();

Uri.Builder builder = Uri.parse("chrome://new-tab-takeover").buildUpon();
builder.appendQueryParameter("wallpaperUrl", sponsoredRichMedia.getWallpaperUrl());
builder.appendQueryParameter("creativeInstanceId", sponsoredRichMedia.getCreativeInstanceId());
builder.appendQueryParameter("placementId", sponsoredRichMedia.getPlacementId());
builder.appendQueryParameter("targetUrl", sponsoredRichMedia.getTargetUrl());

mSponsoredBackgroundWebContents
.getNavigationController()
.loadUrl(new LoadUrlParams(builder.build().toString()));
}

private void setBackgroundImage(NTPImage ntpImage) {
mBgImageView = (ImageView) findViewById(R.id.bg_image_view);
mBgImageView.setScaleType(ImageView.ScaleType.MATRIX);
Expand Down Expand Up @@ -1261,6 +1374,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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
3 changes: 3 additions & 0 deletions android/java/org/chromium/chrome/browser/util/TabUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -236,6 +238,7 @@ public static void openUrlInNewTabInBackground(boolean isIncognito, String url)
}
}

@CalledByNative
public static void openUrlInSameTab(String url) {
try {
BraveActivity braveActivity = BraveActivity.getBraveActivity();
Expand Down
6 changes: 6 additions & 0 deletions android/java/res/layout/new_tab_page_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
android:layout_height="match_parent"
android:contentDescription="@null"/>

<FrameLayout
android:id="@+id/bg_background_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>

<FrameLayout
android:id="@+id/logo_holder"
android:layout_width="match_parent"
Expand Down
7 changes: 6 additions & 1 deletion browser/brave_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ using extensions::ChromeContentBrowserClientExtensionsPart;

#if BUILDFLAG(IS_ANDROID)
#include "brave/browser/ui/webui/brave_wallet/android/android_wallet_page_ui.h"
#include "brave/browser/ui/webui/new_tab_takeover_page/android/new_tab_takeover_page_ui.h"
#include "brave/components/brave_new_tab_ui/new_tab_takeover_page/mojom/new_tab_takeover_page.mojom.h"
#endif // BUILDFLAG(IS_ANDROID)

#if !BUILDFLAG(IS_ANDROID)
Expand Down Expand Up @@ -681,7 +683,10 @@ void BraveContentBrowserClient::RegisterWebUIInterfaceBrokers(
.Add<brave_news::mojom::BraveNewsController>()
.Add<brave_news::mojom::BraveNewsInternals>();
}
#endif
#else
registry.ForWebUI<NewTabTakeoverPageUI>()
.Add<new_tab_takeover_page::mojom::NewTabTakeoverPage>();
#endif // !BUILDFLAG(IS_ANDROID)
}

std::optional<base::UnguessableToken>
Expand Down
50 changes: 46 additions & 4 deletions browser/ntp_background/android/ntp_background_images_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,42 @@ NTPBackgroundImagesBridge::CreateBrandedWallpaper(
ConvertUTF8ToJavaString(env, wallpaper_id ? *wallpaper_id : ""));
}

base::android::ScopedJavaLocalRef<jobject>
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<jobject>();
}

const std::string* creative_instance_id =
data.FindString(ntp_background_images::kCreativeInstanceIDKey);
if (!creative_instance_id) {
return base::android::ScopedJavaLocalRef<jobject>();
}

const std::string* placement_id =
data.FindString(ntp_background_images::kWallpaperIDKey);
if (!placement_id) {
return base::android::ScopedJavaLocalRef<jobject>();
}

const std::string* target_url = data.FindStringByDottedPath(
ntp_background_images::kLogoDestinationURLPath);
if (!target_url) {
return base::android::ScopedJavaLocalRef<jobject>();
}

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<jobject>& obj) {
std::vector<ntp_background_images::TopSite> top_sites =
Expand Down Expand Up @@ -257,12 +293,18 @@ NTPBackgroundImagesBridge::GetCurrentWallpaper(
if (!data)
return base::android::ScopedJavaLocalRef<jobject>();

bool is_background =
// TODO(aseren): Add SponsoredRichMedia support.
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);
}
}

Expand Down
2 changes: 2 additions & 0 deletions browser/ntp_background/android/ntp_background_images_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class NTPBackgroundImagesBridge : public NTPBackgroundImagesService::Observer,
const base::Value::Dict& data);
base::android::ScopedJavaLocalRef<jobject> CreateBrandedWallpaper(
const base::Value::Dict& data);
base::android::ScopedJavaLocalRef<jobject> CreateSponsoredRichMedia(
const base::Value::Dict& data);

raw_ptr<Profile> profile_ = nullptr;
raw_ptr<ViewCounterService> view_counter_service_ = nullptr;
Expand Down
1 change: 1 addition & 0 deletions browser/sources.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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_page/android:new_tab_takeover_page",
"//brave/build/android:jni_headers",
"//brave/components/brave_sync:sync_service_impl_helper",
"//chrome/android:jni_headers",
Expand Down
Loading

0 comments on commit 0ef68e4

Please sign in to comment.