Add needs browser update to see ads alert to rewards NTP widget.

fix https://github.com/brave/brave-browser/issues/21388
This commit is contained in:
Aleksey Seren
2022-05-21 00:08:55 +07:00
parent 03b82ed5dc
commit 0fd7f9c94d
18 changed files with 176 additions and 14 deletions
+3
View File
@@ -37,6 +37,7 @@ source_set("favicon_source") {
source_set("ui") {
# Remove when https://github.com/brave/brave-browser/issues/10614 is resolved
check_includes = false
public_deps = []
sources = [
"webui/brave_adblock_ui.cc",
"webui/brave_adblock_ui.h",
@@ -150,6 +151,8 @@ source_set("ui") {
"webui/settings/brave_relaunch_handler_mac.mm",
]
}
public_deps += [ "//brave/vendor/bat-native-ads" ]
} # !is_android
if (toolkit_views) {
+3 -1
View File
@@ -274,6 +274,8 @@ void CustomizeWebUIHTMLSource(const std::string &name,
{ "rewardsTokenBalance", IDS_REWARDS_WIDGET_TOKEN_BALANCE },
{ "rewardsTokenGrantTitle", IDS_REWARDS_WIDGET_TOKEN_GRANT_TITLE },
{ "rewardsWidgetBraveRewards", IDS_BRAVE_UI_BRAVE_REWARDS },
{ "rewardsBrowserCannotReceiveAds", IDS_REWARDS_BROWSER_CANNOT_RECEIVE_ADS }, // NOLINT
{ "rewardsBrowserNeedsUpdateToSeeAds", IDS_REWARDS_BROWSER_NEEDS_UPDATE_TO_SEE_ADS }, // NOLINT
// Brave Talk Widget
{ "braveTalkWidgetTitle", IDS_BRAVE_TALK_WIDGET_TITLE },
@@ -552,7 +554,7 @@ void CustomizeWebUIHTMLSource(const std::string &name,
{ "view", IDS_BRAVE_REWARDS_LOCAL_ADS_CONFIRMATION_TYPE_VIEW },
{ "rewardsBrowserCannotReceiveAds", IDS_REWARDS_BROWSER_CANNOT_RECEIVE_ADS }, // NOLINT
{ "rewardsBrowserNeedsUpdateToSeeAds", IDS_REWARDS_BROWSER_NEED_UPDATE_TO_SEE_ADS }, // NOLINT
{ "rewardsBrowserNeedsUpdateToSeeAds", IDS_REWARDS_BROWSER_NEEDS_UPDATE_TO_SEE_ADS }, // NOLINT
{ "activityCopy", IDS_BRAVE_UI_ACTIVITY_COPY },
{ "activityNote", IDS_BRAVE_UI_ACTIVITY_NOTE },
@@ -21,7 +21,6 @@
#include "brave/browser/search_engines/search_engine_provider_util.h"
#include "brave/browser/ui/webui/new_tab_page/brave_new_tab_ui.h"
#include "brave/common/pref_names.h"
#include "brave/components/brave_ads/browser/ads_service.h"
#include "brave/components/brave_perf_predictor/common/pref_names.h"
#include "brave/components/brave_today/common/pref_names.h"
#include "brave/components/crypto_dot_com/browser/buildflags/buildflags.h"
@@ -145,6 +144,8 @@ enum class NTPCustomizeUsage { kNeverOpened, kOpened, kOpenedAndEdited, kSize };
const char kNTPCustomizeUsageStatus[] =
"brave.new_tab_page.customize_p3a_usage";
const char kNeedsBrowserUpdateToSeeAds[] = "needsBrowserUpdateToSeeAds";
} // namespace
// static
@@ -176,6 +177,7 @@ bool BraveNewTabMessageHandler::CanPromptBraveTalk(base::Time now) {
return (time_first_run <= talk_prompt_trigger_time);
}
// static
BraveNewTabMessageHandler* BraveNewTabMessageHandler::Create(
content::WebUIDataSource* source,
Profile* profile) {
@@ -183,19 +185,19 @@ BraveNewTabMessageHandler* BraveNewTabMessageHandler::Create(
// Initial Values
// Should only contain data that is static
//
auto* ads_service_ = brave_ads::AdsServiceFactory::GetForProfile(profile);
auto* ads_service = brave_ads::AdsServiceFactory::GetForProfile(profile);
// For safety, default |is_ads_supported_locale_| to true. Better to have
// false positive than falsen egative,
// in which case we would not show "opt out" toggle.
bool is_ads_supported_locale_ = true;
if (!ads_service_) {
bool is_ads_supported_locale = true;
if (!ads_service) {
LOG(ERROR) << "Ads service is not initialized!";
} else {
is_ads_supported_locale_ = ads_service_->IsSupportedLocale();
is_ads_supported_locale = ads_service->IsSupportedLocale();
}
source->AddBoolean("featureFlagBraveNTPSponsoredImagesWallpaper",
is_ads_supported_locale_);
is_ads_supported_locale);
source->AddBoolean("braveTalkPromptAllowed",
BraveNewTabMessageHandler::CanPromptBraveTalk());
@@ -209,6 +211,7 @@ BraveNewTabMessageHandler* BraveNewTabMessageHandler::Create(
BraveNewTabMessageHandler::BraveNewTabMessageHandler(Profile* profile)
: profile_(profile), weak_ptr_factory_(this) {
ads_service_ = brave_ads::AdsServiceFactory::GetForProfile(profile_);
#if BUILDFLAG(ENABLE_TOR)
tor_launcher_factory_ = TorLauncherFactory::GetInstance();
#endif
@@ -245,6 +248,10 @@ void BraveNewTabMessageHandler::RegisterMessages() {
"getNewTabPageTorProperties",
base::BindRepeating(&BraveNewTabMessageHandler::HandleGetTorProperties,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getNewTabAdsData",
base::BindRepeating(&BraveNewTabMessageHandler::HandleGetNewTabAdsData,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"toggleAlternativePrivateSearchEngine",
base::BindRepeating(&BraveNewTabMessageHandler::
@@ -384,6 +391,11 @@ void BraveNewTabMessageHandler::OnJavascriptAllowed() {
if (tor_launcher_factory_)
tor_launcher_factory_->AddObserver(this);
#endif
if (ads_service_) {
ads_service_observation_.Reset();
ads_service_observation_.Observe(ads_service_);
}
}
void BraveNewTabMessageHandler::OnJavascriptDisallowed() {
@@ -392,6 +404,7 @@ void BraveNewTabMessageHandler::OnJavascriptDisallowed() {
if (tor_launcher_factory_)
tor_launcher_factory_->RemoveObserver(this);
#endif
ads_service_observation_.Reset();
weak_ptr_factory_.InvalidateWeakPtrs();
}
@@ -431,6 +444,18 @@ void BraveNewTabMessageHandler::HandleGetTorProperties(
ResolveJavascriptCallback(args[0], data);
}
void BraveNewTabMessageHandler::HandleGetNewTabAdsData(
const base::Value::List& args) {
if (!ads_service_) {
return;
}
AllowJavascript();
base::Value data = GetAdsDataDictionary();
ResolveJavascriptCallback(args[0], data);
}
void BraveNewTabMessageHandler::HandleToggleAlternativeSearchEngineProvider(
const base::Value::List& args) {
brave::ToggleUseAlternativeSearchEngineProvider(profile_);
@@ -617,6 +642,19 @@ void BraveNewTabMessageHandler::OnPreferencesChanged() {
FireWebUIListener("preferences-changed", data);
}
base::Value BraveNewTabMessageHandler::GetAdsDataDictionary() const {
base::Value::Dict ads_data;
bool needs_browser_update_to_see_ads = false;
if (ads_service_) {
needs_browser_update_to_see_ads =
ads_service_->NeedsBrowserUpdateToSeeAds();
}
ads_data.Set(kNeedsBrowserUpdateToSeeAds, needs_browser_update_to_see_ads);
return base::Value(std::move(ads_data));
}
void BraveNewTabMessageHandler::OnTorCircuitEstablished(bool result) {
auto data = GetTorPropertiesDictionary(result, "");
FireWebUIListener("tor-tab-data-updated", data);
@@ -627,3 +665,8 @@ void BraveNewTabMessageHandler::OnTorInitializing(
auto data = GetTorPropertiesDictionary(false, percentage);
FireWebUIListener("tor-tab-data-updated", data);
}
void BraveNewTabMessageHandler::OnNeedsBrowserUpdateToSeeAds() {
base::Value data = GetAdsDataDictionary();
FireWebUIListener("new-tab-ads-data-updated", data);
}
@@ -10,6 +10,8 @@
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "brave/components/brave_ads/browser/ads_service.h"
#include "brave/components/tor/buildflags/buildflags.h"
#include "brave/components/tor/tor_launcher_observer.h"
#include "components/prefs/pref_change_registrar.h"
@@ -19,6 +21,7 @@ class Profile;
namespace base {
class Time;
class Value;
} // namespace base
namespace content {
@@ -35,7 +38,8 @@ class PrefService;
// TODO(simonhong): Migrate to brave_new_tab_page.mojom.
// Handles messages to and from the New Tab Page javascript
class BraveNewTabMessageHandler : public content::WebUIMessageHandler,
public TorLauncherObserver {
public TorLauncherObserver,
public brave_ads::AdsServiceObserver {
public:
explicit BraveNewTabMessageHandler(Profile* profile);
BraveNewTabMessageHandler(const BraveNewTabMessageHandler&) = delete;
@@ -61,6 +65,7 @@ class BraveNewTabMessageHandler : public content::WebUIMessageHandler,
void HandleGetStats(const base::Value::List& args);
void HandleGetPrivateProperties(const base::Value::List& args);
void HandleGetTorProperties(const base::Value::List& args);
void HandleGetNewTabAdsData(const base::Value::List& args);
void HandleSaveNewTabPagePref(const base::Value::List& args);
void HandleToggleAlternativeSearchEngineProvider(
const base::Value::List& args);
@@ -73,16 +78,26 @@ class BraveNewTabMessageHandler : public content::WebUIMessageHandler,
void OnPreferencesChanged();
void OnPrivatePropertiesChanged();
base::Value GetAdsDataDictionary() const;
// TorLauncherObserver:
void OnTorCircuitEstablished(bool result) override;
void OnTorInitializing(const std::string& percentage) override;
// brave_ads::AdsServiceObserver:
void OnNeedsBrowserUpdateToSeeAds() override;
PrefChangeRegistrar pref_change_registrar_;
// Weak pointer.
raw_ptr<Profile> profile_ = nullptr;
raw_ptr<brave_ads::AdsService> ads_service_ = nullptr;
#if BUILDFLAG(ENABLE_TOR)
TorLauncherFactory* tor_launcher_factory_ = nullptr;
#endif
base::ScopedObservation<brave_ads::AdsService, brave_ads::AdsServiceObserver>
ads_service_observation_{this};
base::WeakPtrFactory<BraveNewTabMessageHandler> weak_ptr_factory_;
};
@@ -11,6 +11,7 @@ import { types } from '../constants/new_tab_types'
import { Stats } from '../api/stats'
import { PrivateTabData } from '../api/privateTabData'
import { TorTabData } from '../api/torTabData'
import { NewTabAdsData } from '../api/newTabAdsData'
import { InitialData } from '../api/initialData'
import { CustomBackground } from '../api/background'
@@ -32,6 +33,9 @@ export const privateTabDataUpdated = (data: PrivateTabData) =>
export const torTabDataUpdated = (data: TorTabData) =>
action(types.NEW_TAB_TOR_TAB_DATA_UPDATED, data)
export const newTabAdsDataUpdated = (data: NewTabAdsData) =>
action(types.NEW_TAB_ADS_DATA_UPDATED, data)
export const dismissBrandedWallpaperNotification = (isUserAction: boolean) =>
action(types.NEW_TAB_DISMISS_BRANDED_WALLPAPER_NOTIFICATION, {
isUserAction
+15 -4
View File
@@ -8,6 +8,7 @@ import * as statsAPI from './stats'
import * as privateTabDataAPI from './privateTabData'
import * as torTabDataAPI from './torTabData'
import * as wallpaper from './wallpaper'
import * as newTabAdsDataAPI from './newTabAdsData'
export type InitialData = {
preferences: NewTab.Preferences
@@ -26,6 +27,7 @@ export type PreInitialRewardsData = {
rewardsEnabled: boolean
enabledAds: boolean
adsSupported: boolean
needsBrowserUpdateToSeeAds: boolean
}
export type InitialRewardsData = {
@@ -110,19 +112,28 @@ export async function getInitialData (): Promise<InitialData> {
}
export async function getRewardsPreInitialData (): Promise<PreInitialRewardsData> {
const [rewardsEnabled, enabledAds, adsSupported] = await Promise.all([
const [
rewardsEnabled,
enabledAds,
adsSupported,
adsData
] = await Promise.all([
new Promise<boolean>(
(resolve) => chrome.braveRewards.getRewardsEnabled(resolve)),
new Promise<boolean>(
(resolve) => chrome.braveRewards.getAdsEnabled(resolve)),
new Promise<boolean>(
(resolve) => chrome.braveRewards.getAdsSupported(resolve))
])
(resolve) => chrome.braveRewards.getAdsSupported(resolve)),
newTabAdsDataAPI.getNewTabAdsData()
])
const needsBrowserUpdateToSeeAds = adsData.needsBrowserUpdateToSeeAds
return {
rewardsEnabled,
enabledAds,
adsSupported
adsSupported,
needsBrowserUpdateToSeeAds
}
}
@@ -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 http://mozilla.org/MPL/2.0/.
import * as Cr from 'chrome://resources/js/cr.m'
export type NewTabAdsData = {
needsBrowserUpdateToSeeAds: boolean
}
type NewTabAdsDataUpdatedHandler = (data: NewTabAdsData) => void
export function getNewTabAdsData (): Promise<NewTabAdsData> {
return Cr.sendWithPromise('getNewTabAdsData')
}
export function addChangeListener (listener: NewTabAdsDataUpdatedHandler): void {
Cr.addWebUIListener('new-tab-ads-data-updated', listener)
}
@@ -9,6 +9,7 @@ import * as statsAPI from './api/stats'
import * as topSitesAPI from './api/topSites'
import * as privateTabDataAPI from './api/privateTabData'
import * as torTabDataAPI from './api/torTabData'
import * as newTabAdsDataAPI from './api/newTabAdsData'
import getNTPBrowserAPI, { CustomBackground } from './api/background'
import { getInitialData, getRewardsInitialData, getRewardsPreInitialData } from './api/initialData'
@@ -28,6 +29,10 @@ async function updateTorTabData (data: torTabDataAPI.TorTabData) {
getActions().torTabDataUpdated(data)
}
async function updateNewTabAdsData (data: newTabAdsDataAPI.NewTabAdsData) {
getActions().newTabAdsDataUpdated(data)
}
function onRewardsToggled (prefData: NewTab.Preferences): void {
if (prefData.showRewards) {
rewardsInitData()
@@ -61,6 +66,7 @@ export function wireApiEventsToStore () {
preferencesAPI.addChangeListener(onRewardsToggled)
privateTabDataAPI.addChangeListener(updatePrivateTabData)
torTabDataAPI.addChangeListener(updateTorTabData)
newTabAdsDataAPI.addChangeListener(updateNewTabAdsData)
getNTPBrowserAPI().addCustomBackgroundUpdatedListener(onCustomBackgroundUpdated)
})
.catch(e => {
@@ -45,6 +45,7 @@ export function RewardsContextAdapter (props: { children: React.ReactNode }) {
export interface RewardsProps {
rewardsEnabled: boolean
enabledAds: boolean
needsBrowserUpdateToSeeAds: boolean
balance: NewTab.RewardsBalance
externalWallet?: RewardsExtension.ExternalWallet
report?: NewTab.RewardsBalanceReport
@@ -103,6 +104,7 @@ export const RewardsWidget = createWidget((props: RewardsProps) => {
rewardsEnabled={props.rewardsEnabled}
adsEnabled={props.enabledAds}
adsSupported={Boolean(props.adsSupported)}
needsBrowserUpdateToSeeAds={props.needsBrowserUpdateToSeeAds}
rewardsBalance={props.balance.total}
exchangeCurrency='USD'
exchangeRate={props.parameters.rate}
@@ -16,6 +16,7 @@ export const enum types {
NEW_TAB_STATS_UPDATED = '@@newtab/NEW_TAB_STATS_UPDATED',
NEW_TAB_PRIVATE_TAB_DATA_UPDATED = '@@newtab/NEW_TAB_PRIVATE_TAB_DATA_UPDATED',
NEW_TAB_TOR_TAB_DATA_UPDATED = '@@newtab/NEW_TAB_TOR_TAB_DATA_UPDATED',
NEW_TAB_ADS_DATA_UPDATED = '@@newtab/NEW_TAB_ADS_DATA_UPDATED',
NEW_TAB_PREFERENCES_UPDATED = '@@newtab/NEW_TAB_PREFERENCES_UPDATED',
NEW_TAB_DISMISS_BRANDED_WALLPAPER_NOTIFICATION = '@@newtab/NEW_TAB_DISMISS_BRANDED_WALLPAPER_NOTIFICATION',
NEW_TAB_SET_INITIAL_DATA = '@@newtab/NEW_TAB_SET_INITIAL_DATA',
@@ -22,6 +22,7 @@ import { setMostVisitedSettings } from '../api/topSites'
// Utils
import { handleWidgetPrefsChange } from './stack_widget_reducer'
import { NewTabAdsData } from '../api/newTabAdsData'
let sideEffectState: NewTab.State = storage.load()
@@ -137,6 +138,11 @@ export const newTabReducer: Reducer<NewTab.State | undefined> = (state: NewTab.S
}
break
case types.NEW_TAB_ADS_DATA_UPDATED:
const newTabAdsData = payload as NewTabAdsData
state.rewardsState.needsBrowserUpdateToSeeAds = newTabAdsData.needsBrowserUpdateToSeeAds
break
case types.NEW_TAB_DISMISS_BRANDED_WALLPAPER_NOTIFICATION:
const { isUserAction } = payload as DismissBrandedWallpaperNotificationPayload
// Save persisted data.
@@ -87,7 +87,8 @@ const rewardsReducer: Reducer<NewTab.State | undefined> = (state: NewTab.State,
...state.rewardsState,
rewardsEnabled: preInitialRewardsDataPayload.rewardsEnabled,
enabledAds: preInitialRewardsDataPayload.enabledAds,
adsSupported: preInitialRewardsDataPayload.adsSupported
adsSupported: preInitialRewardsDataPayload.adsSupported,
needsBrowserUpdateToSeeAds: preInitialRewardsDataPayload.needsBrowserUpdateToSeeAds
}
}
break
@@ -74,6 +74,7 @@ export const defaultState: NewTab.State = {
dismissedNotifications: [],
rewardsEnabled: false,
enabledAds: false,
needsBrowserUpdateToSeeAds: false,
adsSupported: false,
promotions: [],
totalContribution: 0.0,
@@ -182,6 +182,28 @@ export const pendingRewards = styled.div`
}
`
export const needsBrowserUpdateView = styled.div`
display: block;
align-items: center;
justify-content: start;
background: #FDF1F2;
padding: 5px;
border-radius: 6px;
`
export const needsBrowserUpdateContentHeader = styled.div`
margin: 5px;
font-size: 13px;
font-weight: 600;
color: var(--brave-palette-neutral800);
`
export const needsBrowserUpdateContentBody = styled.div`
margin: 5px;
font-size: 13px;
color: var(--brave-palette-neutral800);
`
export const progressHeader = styled.div`
margin-top: 16px;
display: flex;
@@ -64,6 +64,7 @@ interface Props {
rewardsEnabled: boolean
adsEnabled: boolean
adsSupported: boolean
needsBrowserUpdateToSeeAds: boolean
rewardsBalance: number
exchangeRate: number
exchangeCurrency: string
@@ -118,6 +119,28 @@ export function RewardsCard (props: Props) {
)
}
if (props.needsBrowserUpdateToSeeAds && props.adsSupported) {
return (
<style.balance>
<style.needsBrowserUpdateView>
<style.needsBrowserUpdateContentHeader>
{getString('rewardsBrowserCannotReceiveAds')}
</style.needsBrowserUpdateContentHeader>
<style.needsBrowserUpdateContentBody>
{getString('rewardsBrowserNeedsUpdateToSeeAds')}
</style.needsBrowserUpdateContentBody>
</style.needsBrowserUpdateView>
<style.pendingRewards>
<PaymentStatusView
earningsLastMonth={props.earningsLastMonth}
earningsReceived={props.earningsReceived}
nextPaymentDate={props.nextPaymentDate}
/>
</style.pendingRewards>
</style.balance>
)
}
const showPending = shouldRenderPendingRewards(
props.earningsLastMonth,
props.nextPaymentDate)
@@ -41,6 +41,7 @@ export function Card () {
rewardsEnabled={true}
adsEnabled={true}
adsSupported={true}
needsBrowserUpdateToSeeAds={false}
rewardsBalance={91.5812}
exchangeCurrency='USD'
exchangeRate={0.82}
+1
View File
@@ -156,6 +156,7 @@ declare namespace NewTab {
adsAccountStatement: AdsAccountStatement
dismissedNotifications: string[]
enabledAds: boolean
needsBrowserUpdateToSeeAds: boolean
promotions: Promotion[]
parameters: RewardsParameters
totalContribution: number
@@ -534,7 +534,7 @@
</message>
<message name="IDS_REWARDS_BROWSER_CANNOT_RECEIVE_ADS" desc="">Oops! Your browser cannot receive Brave Private Ads.</message>
<message name="IDS_REWARDS_BROWSER_NEED_UPDATE_TO_SEE_ADS" desc="">Your browser needs to be updated to continue seeing ads.</message>
<message name="IDS_REWARDS_BROWSER_NEEDS_UPDATE_TO_SEE_ADS" desc="">Your browser needs to be updated to continue seeing ads.</message>
<!-- WebUI rewards internals resources -->
<message name="IDS_BRAVE_REWARDS_INTERNALS_ADS_NOT_INITIALIZED" desc="Ads not initialized">Ads not initialized, please refresh the page.</message>