Skip to content

Commit

Permalink
Optimize ad serving based upon local user browser activity
Browse files Browse the repository at this point in the history
  • Loading branch information
tmancey committed Feb 27, 2021
1 parent c83eb4a commit 99aa738
Show file tree
Hide file tree
Showing 61 changed files with 3,296 additions and 424 deletions.
2 changes: 1 addition & 1 deletion components/brave_ads/browser/ads_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void AdsService::RegisterProfilePrefs(
registry->RegisterUint64Pref(ads::prefs::kAdsPerHour,
ads::kDefaultAdNotificationsPerHour);

registry->RegisterIntegerPref(ads::prefs::kIdleThreshold, 15);
registry->RegisterIntegerPref(ads::prefs::kIdleTimeThreshold, 15);

registry->RegisterBooleanPref(ads::prefs::kShouldAllowAdsSubdivisionTargeting,
false);
Expand Down
2 changes: 2 additions & 0 deletions components/brave_ads/browser/ads_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class AdsService : public KeyedService {
virtual void ChangeLocale(const std::string& locale) = 0;

virtual void OnPageLoaded(const SessionID& tab_id,
const int32_t page_transition_type,
const bool has_user_gesture,
const std::vector<GURL>& redirect_chain,
const std::string& content) = 0;

Expand Down
55 changes: 38 additions & 17 deletions components/brave_ads/browser/ads_service_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ AdsServiceImpl::AdsServiceImpl(Profile* profile)
base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
base_path_(profile_->GetPath().AppendASCII("ads_service")),
last_idle_state_(ui::IdleState::IDLE_STATE_ACTIVE),
last_idle_time_(0),
display_service_(NotificationDisplayService::GetForProfile(profile_)),
rewards_service_(
brave_rewards::RewardsServiceFactory::GetForProfile(profile_)),
Expand Down Expand Up @@ -300,6 +301,8 @@ void AdsServiceImpl::ChangeLocale(const std::string& locale) {
}

void AdsServiceImpl::OnPageLoaded(const SessionID& tab_id,
const int32_t page_transition_type,
const bool has_user_gesture,
const std::vector<GURL>& redirect_chain,
const std::string& content) {
if (!connected()) {
Expand All @@ -311,7 +314,8 @@ void AdsServiceImpl::OnPageLoaded(const SessionID& tab_id,
redirect_chain_as_strings.push_back(url.spec());
}

bat_ads_->OnPageLoaded(tab_id.id(), redirect_chain_as_strings, content);
bat_ads_->OnPageLoaded(tab_id.id(), page_transition_type, has_user_gesture,
redirect_chain_as_strings, content);
}

void AdsServiceImpl::OnMediaStart(const SessionID& tab_id) {
Expand Down Expand Up @@ -604,7 +608,7 @@ void AdsServiceImpl::Initialize() {
base::Bind(&AdsServiceImpl::OnPrefsChanged, base::Unretained(this)));

profile_pref_change_registrar_.Add(
ads::prefs::kIdleThreshold,
ads::prefs::kIdleTimeThreshold,
base::Bind(&AdsServiceImpl::OnPrefsChanged, base::Unretained(this)));

profile_pref_change_registrar_.Add(
Expand Down Expand Up @@ -884,26 +888,43 @@ void AdsServiceImpl::StartCheckIdleStateTimer() {
}

void AdsServiceImpl::CheckIdleState() {
auto idle_state = ui::CalculateIdleState(GetIdleThreshold());
ProcessIdleState(idle_state);
const int idle_threshold = GetIdleTimeThreshold();
const ui::IdleState idle_state = ui::CalculateIdleState(idle_threshold);
ProcessIdleState(idle_state, last_idle_time_);

last_idle_time_ = ui::CalculateIdleTime();
}

void AdsServiceImpl::ProcessIdleState(const ui::IdleState idle_state) {
void AdsServiceImpl::ProcessIdleState(const ui::IdleState idle_state,
const int idle_time) {
if (!connected() || idle_state == last_idle_state_) {
return;
}

if (idle_state == ui::IdleState::IDLE_STATE_ACTIVE) {
bat_ads_->OnUnIdle();
} else {
bat_ads_->OnIdle();
switch (idle_state) {
case ui::IdleState::IDLE_STATE_ACTIVE: {
const bool was_locked =
last_idle_state_ == ui::IdleState::IDLE_STATE_LOCKED;
bat_ads_->OnUnIdle(idle_time, was_locked);
break;
}

case ui::IdleState::IDLE_STATE_IDLE:
case ui::IdleState::IDLE_STATE_LOCKED: {
bat_ads_->OnIdle();
break;
}

case ui::IdleState::IDLE_STATE_UNKNOWN: {
break;
}
}

last_idle_state_ = idle_state;
}

int AdsServiceImpl::GetIdleThreshold() {
return GetIntegerPref(ads::prefs::kIdleThreshold);
int AdsServiceImpl::GetIdleTimeThreshold() {
return GetIntegerPref(ads::prefs::kIdleTimeThreshold);
}

void AdsServiceImpl::OnShow(Profile* profile, const std::string& uuid) {
Expand Down Expand Up @@ -1545,17 +1566,17 @@ bool AdsServiceImpl::IsUpgradingFromPreBraveAdsBuild() {
// Brave ads was hidden in 0.62.x however due to a bug |prefs::kEnabled| was
// set to true causing "https://github.com/brave/brave-browser/issues/5434"

// |prefs::kIdleThreshold| was not serialized in 0.62.x
// |prefs::kIdleTimeThreshold| was not serialized in 0.62.x

// |prefs::kVersion| was introduced in 0.63.x

// We can detect if we are upgrading from a pre Brave ads build by checking
// |prefs::kEnabled| is set to true, |prefs::kIdleThreshold| does not exist,
// |prefs::kVersion| does not exist and it is not the first time the browser
// has run for this user
// |prefs::kEnabled| is set to true, |prefs::kIdleTimeThreshold| does not
// exist, |prefs::kVersion| does not exist and it is not the first time the
// browser has run for this user
#if !defined(OS_ANDROID)
return GetBooleanPref(ads::prefs::kEnabled) &&
!PrefExists(ads::prefs::kIdleThreshold) &&
!PrefExists(ads::prefs::kIdleTimeThreshold) &&
!PrefExists(prefs::kVersion) && !first_run::IsChromeFirstRun();
#else
return false;
Expand Down Expand Up @@ -1638,7 +1659,7 @@ void AdsServiceImpl::OnPrefsChanged(const std::string& pref) {

// Record P3A.
brave_rewards::UpdateAdsP3AOnPreferenceChange(profile_->GetPrefs(), pref);
} else if (pref == ads::prefs::kIdleThreshold) {
} else if (pref == ads::prefs::kIdleTimeThreshold) {
StartCheckIdleStateTimer();
} else if (pref == brave_rewards::prefs::kWalletBrave) {
OnWalletUpdated();
Expand Down
7 changes: 5 additions & 2 deletions components/brave_ads/browser/ads_service_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class AdsServiceImpl : public AdsService,
void ChangeLocale(const std::string& locale) override;

void OnPageLoaded(const SessionID& tab_id,
const int32_t page_transition_type,
const bool has_user_gesture,
const std::vector<GURL>& redirect_chain,
const std::string& content) override;

Expand Down Expand Up @@ -199,8 +201,8 @@ class AdsServiceImpl : public AdsService,

void StartCheckIdleStateTimer();
void CheckIdleState();
void ProcessIdleState(const ui::IdleState idle_state);
int GetIdleThreshold();
void ProcessIdleState(const ui::IdleState idle_state, const int idle_time);
int GetIdleTimeThreshold();

void OnShow(Profile* profile, const std::string& uuid);
void OnClose(Profile* profile,
Expand Down Expand Up @@ -404,6 +406,7 @@ class AdsServiceImpl : public AdsService,
std::unique_ptr<ads::Database> database_;

ui::IdleState last_idle_state_;
int last_idle_time_;

base::RepeatingTimer idle_poll_timer_;

Expand Down
74 changes: 45 additions & 29 deletions components/brave_ads/browser/ads_tab_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/resource/resource_bundle.h"

#if !defined(OS_ANDROID)
Expand All @@ -33,7 +34,7 @@ AdsTabHelper::AdsTabHelper(content::WebContents* web_contents)
ads_service_(nullptr),
is_active_(false),
is_browser_active_(true),
run_distiller_(false),
should_process_(false),
weak_factory_(this) {
if (!tab_id_.is_valid()) {
return;
Expand Down Expand Up @@ -84,47 +85,50 @@ void AdsTabHelper::RunIsolatedJavaScript(
}

void AdsTabHelper::OnJavaScriptResult(base::Value value) {
DCHECK(ads_service_ && ads_service_->IsEnabled());
if (!IsAdsEnabled()) {
return;
}

DCHECK(value.is_string());
std::string content;
value.GetAsString(&content);

ads_service_->OnPageLoaded(tab_id_, redirect_chain_, content);
ads_service_->OnPageLoaded(tab_id_, page_transition_, has_user_gesture_,
redirect_chain_, content);
}

void AdsTabHelper::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame() ||
DCHECK(navigation_handle);

if (!IsAdsEnabled() || !navigation_handle->IsInMainFrame() ||
!navigation_handle->HasCommitted() || !tab_id_.is_valid()) {
return;
}

redirect_chain_ = navigation_handle->GetRedirectChain();

if (navigation_handle->IsSameDocument()) {
if (!IsAdsEnabled()) {
// Do not call the ads service if the ad service isn't enabled
return;
}
const ui::PageTransition page_transition =
navigation_handle->GetPageTransition();

content::RenderFrameHost* render_frame_host =
navigation_handle->GetRenderFrameHost();
page_transition_ = static_cast<int32_t>(page_transition);

RunIsolatedJavaScript(render_frame_host);
has_user_gesture_ = navigation_handle->HasUserGesture();

if (!navigation_handle->IsSameDocument()) {
should_process_ = navigation_handle->GetRestoreType() ==
content::RestoreType::kNotRestored;
return;
}

bool was_restored =
navigation_handle->GetRestoreType() == content::RestoreType::kRestored;
content::RenderFrameHost* render_frame_host =
navigation_handle->GetRenderFrameHost();

run_distiller_ = !was_restored;
RunIsolatedJavaScript(render_frame_host);
}

void AdsTabHelper::DocumentOnLoadCompletedInMainFrame() {
if (!IsAdsEnabled() || !run_distiller_) {
// Do not start distilling if the ad service isn't enabled
if (!IsAdsEnabled() || !should_process_) {
return;
}

Expand All @@ -140,6 +144,8 @@ void AdsTabHelper::DocumentOnLoadCompletedInMainFrame() {

void AdsTabHelper::DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) {
DCHECK(render_frame_host);

if (render_frame_host->GetParent()) {
return;
}
Expand Down Expand Up @@ -168,16 +174,22 @@ void AdsTabHelper::MediaStoppedPlaying(
}

void AdsTabHelper::OnVisibilityChanged(content::Visibility visibility) {
bool old_active = is_active_;
if (visibility == content::Visibility::HIDDEN) {
is_active_ = false;
} else if (visibility == content::Visibility::OCCLUDED) {
is_active_ = false;
} else if (visibility == content::Visibility::VISIBLE) {
is_active_ = true;
const bool old_is_active = is_active_;

switch (visibility) {
case content::Visibility::HIDDEN:
case content::Visibility::OCCLUDED: {
is_active_ = false;
break;
}

case content::Visibility::VISIBLE: {
is_active_ = true;
break;
}
}

if (old_active == is_active_) {
if (old_is_active == is_active_) {
return;
}

Expand All @@ -200,27 +212,31 @@ void AdsTabHelper::OnBrowserSetLastActive(Browser* browser) {
return;
}

bool old_active = is_browser_active_;
const bool old_is_browser_active = is_browser_active_;

if (browser->tab_strip_model()->GetIndexOfWebContents(web_contents()) !=
TabStripModel::kNoTab) {
is_browser_active_ = true;
}

if (old_active == is_browser_active_) {
if (old_is_browser_active == is_browser_active_) {
return;
}

TabUpdated();
}

void AdsTabHelper::OnBrowserNoLongerActive(Browser* browser) {
bool old_active = is_browser_active_;
DCHECK(browser);

const bool old_is_browser_active = is_browser_active_;

if (browser->tab_strip_model()->GetIndexOfWebContents(web_contents()) !=
TabStripModel::kNoTab) {
is_browser_active_ = false;
}

if (old_active == is_browser_active_) {
if (old_is_browser_active == is_browser_active_) {
return;
}

Expand Down
7 changes: 5 additions & 2 deletions components/brave_ads/browser/ads_tab_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#ifndef BRAVE_COMPONENTS_BRAVE_ADS_BROWSER_ADS_TAB_HELPER_H_
#define BRAVE_COMPONENTS_BRAVE_ADS_BROWSER_ADS_TAB_HELPER_H_

#include <stdint.h>

#include <string>
#include <vector>

Expand Down Expand Up @@ -87,8 +89,9 @@ class AdsTabHelper : public content::WebContentsObserver,
bool is_active_;
bool is_browser_active_;
std::vector<GURL> redirect_chain_;

bool run_distiller_;
int32_t page_transition_;
bool has_user_gesture_;
bool should_process_;

base::WeakPtrFactory<AdsTabHelper> weak_factory_;
WEB_CONTENTS_USER_DATA_KEY_DECL();
Expand Down
7 changes: 7 additions & 0 deletions components/brave_ads/test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ source_set("brave_ads_unit_tests") {
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/bandits/epsilon_greedy_bandit_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/purchase_intent/purchase_intent_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/text_classification/text_classification_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/user_activity/user_activity_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/exclusion_rules/conversion_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/exclusion_rules/daily_cap_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/exclusion_rules/daypart_frequency_cap_unittest.cc",
Expand Down Expand Up @@ -93,6 +94,7 @@ source_set("brave_ads_unit_tests") {
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/promoted_content_ads_per_hour_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/unblinded_tokens_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/user_activity_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/idle_time_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/legacy_migration/legacy_migration_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/locale/country_code_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/locale/subdivision_code_util_unittest.cc",
Expand All @@ -112,6 +114,7 @@ source_set("brave_ads_unit_tests") {
"//brave/vendor/bat-native-ads/src/bat/ads/internal/server/ads_server_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/server/confirmations_server_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/server/rewards_server_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/server/via_header_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/string_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/tab_manager/tab_manager_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/tokens/redeem_unblinded_payment_tokens/redeem_unblinded_payment_tokens_delegate_mock.cc",
Expand All @@ -133,7 +136,11 @@ source_set("brave_ads_unit_tests") {
"//brave/vendor/bat-native-ads/src/bat/ads/internal/unittest_util.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/unittest_util.h",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/url_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/user_activity/page_transition_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/user_activity/user_activity_scoring_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/user_activity/user_activity_scoring_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/user_activity/user_activity_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/user_activity/user_activity_util_unittest.cc",
]

if (!is_android) {
Expand Down
Loading

0 comments on commit 99aa738

Please sign in to comment.