Commit d7a6dc71 authored by Colin Blundell's avatar Colin Blundell Committed by Chromium LUCI CQ

[Subresource Filter] Handle ads violations in ProfileInteractionManager

This CL moves the implementation of
ChromeSubresourceFilterClient::OnAdsViolationTriggered() to
ProfileInteractionManager, with the former now just calling through to
the latter. In subsequent work we will eliminate the callthrough to the
client altogether, thus having this logic be shared with WebLayer. In
this CL, however, there is no behavioral change.

Bug: 1116095
Change-Id: Ic315394b20e107d3eb0180bbf157a2a8cdb23118
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2578838
Commit-Queue: Colin Blundell <blundell@chromium.org>
Reviewed-by: default avatarCharlie Harrison <csharrison@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836050}
parent 1664cd79
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
#include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/ukm_source_id.h" #include "services/metrics/public/cpp/ukm_source_id.h"
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
...@@ -39,8 +40,8 @@ ...@@ -39,8 +40,8 @@
ChromeSubresourceFilterClient::ChromeSubresourceFilterClient( ChromeSubresourceFilterClient::ChromeSubresourceFilterClient(
content::WebContents* web_contents) content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) { : web_contents_(web_contents) {
DCHECK(web_contents); DCHECK(web_contents_);
profile_context_ = SubresourceFilterProfileContextFactory::GetForProfile( profile_context_ = SubresourceFilterProfileContextFactory::GetForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext())); Profile::FromBrowserContext(web_contents->GetBrowserContext()));
profile_interaction_manager_ = profile_interaction_manager_ =
...@@ -78,14 +79,6 @@ ChromeSubresourceFilterClient* ChromeSubresourceFilterClient::FromWebContents( ...@@ -78,14 +79,6 @@ ChromeSubresourceFilterClient* ChromeSubresourceFilterClient::FromWebContents(
throttle_manager->client()); throttle_manager->client());
} }
void ChromeSubresourceFilterClient::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (navigation_handle->HasCommitted() && navigation_handle->IsInMainFrame() &&
!navigation_handle->IsSameDocument()) {
ads_violation_triggered_for_last_committed_navigation_ = false;
}
}
void ChromeSubresourceFilterClient::OnReloadRequested() { void ChromeSubresourceFilterClient::OnReloadRequested() {
// TODO(crbug.com/1116095): Once ContentSubresourceFilterThrottleManager knows // TODO(crbug.com/1116095): Once ContentSubresourceFilterThrottleManager knows
// about ProfileInteractionManager, this method can move entirely into // about ProfileInteractionManager, this method can move entirely into
...@@ -95,7 +88,7 @@ void ChromeSubresourceFilterClient::OnReloadRequested() { ...@@ -95,7 +88,7 @@ void ChromeSubresourceFilterClient::OnReloadRequested() {
} }
void ChromeSubresourceFilterClient::ShowNotification() { void ChromeSubresourceFilterClient::ShowNotification() {
const GURL& top_level_url = web_contents()->GetLastCommittedURL(); const GURL& top_level_url = web_contents_->GetLastCommittedURL();
if (profile_context_->settings_manager()->ShouldShowUIForSite( if (profile_context_->settings_manager()->ShouldShowUIForSite(
top_level_url)) { top_level_url)) {
ShowUI(top_level_url); ShowUI(top_level_url);
...@@ -149,46 +142,15 @@ ChromeSubresourceFilterClient::OnPageActivationComputed( ...@@ -149,46 +142,15 @@ ChromeSubresourceFilterClient::OnPageActivationComputed(
return effective_activation_level; return effective_activation_level;
} }
// TODO(https://crbug.com/1131969): Consider adding reporting when
// ads violations are triggered.
void ChromeSubresourceFilterClient::OnAdsViolationTriggered( void ChromeSubresourceFilterClient::OnAdsViolationTriggered(
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
subresource_filter::mojom::AdsViolation triggered_violation) { subresource_filter::mojom::AdsViolation triggered_violation) {
// Only trigger violations once per navigation. The ads intervention // TODO(crbug.com/1116095): Once ContentSubresourceFilterThrottleManager knows
// manager ignores all interventions after recording an intervention // about ProfileInteractionManager, it can invoke the
// for the intervention duration, however, a page that began a navigation // ProfileInteractionManager directly and
// before the intervention duration and was still alive after the duration // SubresourceFilterClient::OnAdsViolationTriggered() can be eliminated.
// could re-trigger an ads intervention. profile_interaction_manager_->OnAdsViolationTriggered(rfh,
if (ads_violation_triggered_for_last_committed_navigation_) triggered_violation);
return;
// If the feature is disabled, simulate ads interventions as if we were
// enforcing on ads: do not record new interventions if we would be enforcing
// an intervention on ads already.
//
// TODO(https://crbug.com/1131971): Add support for enabling ads interventions
// separately for different ads violations.
const GURL& url = rfh->GetLastCommittedURL();
base::Optional<
subresource_filter::AdsInterventionManager::LastAdsIntervention>
last_intervention =
profile_context_->ads_intervention_manager()->GetLastAdsIntervention(
url);
// TODO(crbug.com/1131971): If a host triggers multiple times on a single
// navigate and the durations don't match, we'll use the last duration rather
// than the longest. The metadata should probably store the activation with
// the longest duration.
if (last_intervention &&
last_intervention->duration_since <
subresource_filter::AdsInterventionManager::GetInterventionDuration(
last_intervention->ads_violation)) {
return;
}
profile_context_->ads_intervention_manager()
->TriggerAdsInterventionForUrlOnSubsequentLoads(url, triggered_violation);
ads_violation_triggered_for_last_committed_navigation_ = true;
} }
const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
...@@ -210,7 +172,7 @@ void ChromeSubresourceFilterClient::ToggleForceActivationInCurrentWebContents( ...@@ -210,7 +172,7 @@ void ChromeSubresourceFilterClient::ToggleForceActivationInCurrentWebContents(
void ChromeSubresourceFilterClient::ShowUI(const GURL& url) { void ChromeSubresourceFilterClient::ShowUI(const GURL& url) {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
InfoBarService* infobar_service = InfoBarService* infobar_service =
InfoBarService::FromWebContents(web_contents()); InfoBarService::FromWebContents(web_contents_);
subresource_filter::AdsBlockedInfobarDelegate::Create(infobar_service); subresource_filter::AdsBlockedInfobarDelegate::Create(infobar_service);
#endif #endif
// TODO(https://crbug.com/1103176): Plumb the actual frame reference here // TODO(https://crbug.com/1103176): Plumb the actual frame reference here
...@@ -219,7 +181,7 @@ void ChromeSubresourceFilterClient::ShowUI(const GURL& url) { ...@@ -219,7 +181,7 @@ void ChromeSubresourceFilterClient::ShowUI(const GURL& url) {
// comes from a specific frame). // comes from a specific frame).
content_settings::PageSpecificContentSettings* content_settings = content_settings::PageSpecificContentSettings* content_settings =
content_settings::PageSpecificContentSettings::GetForFrame( content_settings::PageSpecificContentSettings::GetForFrame(
web_contents()->GetMainFrame()); web_contents_->GetMainFrame());
content_settings->OnContentBlocked(ContentSettingsType::ADS); content_settings->OnContentBlocked(ContentSettingsType::ADS);
subresource_filter::ContentSubresourceFilterThrottleManager::LogAction( subresource_filter::ContentSubresourceFilterThrottleManager::LogAction(
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "base/macros.h" #include "base/macros.h"
#include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings.h"
#include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h"
#include "content/public/browser/web_contents_observer.h"
class GURL; class GURL;
...@@ -29,8 +28,7 @@ class SubresourceFilterProfileContext; ...@@ -29,8 +28,7 @@ class SubresourceFilterProfileContext;
// Chrome implementation of SubresourceFilterClient. Instances are associated // Chrome implementation of SubresourceFilterClient. Instances are associated
// with and owned by ContentSubresourceFilterThrottleManager instances. // with and owned by ContentSubresourceFilterThrottleManager instances.
class ChromeSubresourceFilterClient class ChromeSubresourceFilterClient
: public content::WebContentsObserver, : public subresource_filter::SubresourceFilterClient {
public subresource_filter::SubresourceFilterClient {
public: public:
explicit ChromeSubresourceFilterClient(content::WebContents* web_contents); explicit ChromeSubresourceFilterClient(content::WebContents* web_contents);
~ChromeSubresourceFilterClient() override; ~ChromeSubresourceFilterClient() override;
...@@ -47,10 +45,6 @@ class ChromeSubresourceFilterClient ...@@ -47,10 +45,6 @@ class ChromeSubresourceFilterClient
static ChromeSubresourceFilterClient* FromWebContents( static ChromeSubresourceFilterClient* FromWebContents(
content::WebContents* web_contents); content::WebContents* web_contents);
// content::WebContentsObserver:
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
// SubresourceFilterClient: // SubresourceFilterClient:
void ShowNotification() override; void ShowNotification() override;
subresource_filter::mojom::ActivationLevel OnPageActivationComputed( subresource_filter::mojom::ActivationLevel OnPageActivationComputed(
...@@ -72,6 +66,8 @@ class ChromeSubresourceFilterClient ...@@ -72,6 +66,8 @@ class ChromeSubresourceFilterClient
private: private:
void ShowUI(const GURL& url); void ShowUI(const GURL& url);
content::WebContents* web_contents_;
std::unique_ptr<subresource_filter::ContentSubresourceFilterThrottleManager> std::unique_ptr<subresource_filter::ContentSubresourceFilterThrottleManager>
throttle_manager_; throttle_manager_;
...@@ -82,8 +78,6 @@ class ChromeSubresourceFilterClient ...@@ -82,8 +78,6 @@ class ChromeSubresourceFilterClient
std::unique_ptr<subresource_filter::ProfileInteractionManager> std::unique_ptr<subresource_filter::ProfileInteractionManager>
profile_interaction_manager_; profile_interaction_manager_;
bool ads_violation_triggered_for_last_committed_navigation_ = false;
// Corresponds to a devtools command which triggers filtering on all page // Corresponds to a devtools command which triggers filtering on all page
// loads. We must be careful to ensure this boolean does not persist after the // loads. We must be careful to ensure this boolean does not persist after the
// devtools window is closed, which should be handled by the devtools system. // devtools window is closed, which should be handled by the devtools system.
......
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
#include "components/subresource_filter/content/browser/profile_interaction_manager.h" #include "components/subresource_filter/content/browser/profile_interaction_manager.h"
#include "base/logging.h" #include "base/logging.h"
#include "components/subresource_filter/content/browser/ads_intervention_manager.h"
#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
#include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h"
#include "components/subresource_filter/content/browser/subresource_filter_profile_context.h" #include "components/subresource_filter/content/browser/subresource_filter_profile_context.h"
#include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
namespace subresource_filter { namespace subresource_filter {
...@@ -23,6 +26,14 @@ ProfileInteractionManager::ProfileInteractionManager( ...@@ -23,6 +26,14 @@ ProfileInteractionManager::ProfileInteractionManager(
ProfileInteractionManager::~ProfileInteractionManager() = default; ProfileInteractionManager::~ProfileInteractionManager() = default;
void ProfileInteractionManager::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (navigation_handle->HasCommitted() && navigation_handle->IsInMainFrame() &&
!navigation_handle->IsSameDocument()) {
ads_violation_triggered_for_last_committed_navigation_ = false;
}
}
void ProfileInteractionManager::OnReloadRequested() { void ProfileInteractionManager::OnReloadRequested() {
ContentSubresourceFilterThrottleManager::LogAction( ContentSubresourceFilterThrottleManager::LogAction(
SubresourceFilterAction::kAllowlistedSite); SubresourceFilterAction::kAllowlistedSite);
...@@ -32,4 +43,44 @@ void ProfileInteractionManager::OnReloadRequested() { ...@@ -32,4 +43,44 @@ void ProfileInteractionManager::OnReloadRequested() {
web_contents()->GetController().Reload(content::ReloadType::NORMAL, true); web_contents()->GetController().Reload(content::ReloadType::NORMAL, true);
} }
// TODO(https://crbug.com/1131969): Consider adding reporting when
// ads violations are triggered.
void ProfileInteractionManager::OnAdsViolationTriggered(
content::RenderFrameHost* rfh,
mojom::AdsViolation triggered_violation) {
// Only trigger violations once per navigation. The ads intervention
// manager ignores all interventions after recording an intervention
// for the intervention duration, however, a page that began a navigation
// before the intervention duration and was still alive after the duration
// could re-trigger an ads intervention.
if (ads_violation_triggered_for_last_committed_navigation_)
return;
// If the feature is disabled, simulate ads interventions as if we were
// enforcing on ads: do not record new interventions if we would be enforcing
// an intervention on ads already.
//
// TODO(https://crbug.com/1131971): Add support for enabling ads interventions
// separately for different ads violations.
const GURL& url = rfh->GetLastCommittedURL();
base::Optional<AdsInterventionManager::LastAdsIntervention>
last_intervention =
profile_context_->ads_intervention_manager()->GetLastAdsIntervention(
url);
// TODO(crbug.com/1131971): If a host triggers multiple times on a single
// navigate and the durations don't match, we'll use the last duration rather
// than the longest. The metadata should probably store the activation with
// the longest duration.
if (last_intervention && last_intervention->duration_since <
AdsInterventionManager::GetInterventionDuration(
last_intervention->ads_violation)) {
return;
}
profile_context_->ads_intervention_manager()
->TriggerAdsInterventionForUrlOnSubsequentLoads(url, triggered_violation);
ads_violation_triggered_for_last_committed_navigation_ = true;
}
} // namespace subresource_filter } // namespace subresource_filter
...@@ -5,9 +5,11 @@ ...@@ -5,9 +5,11 @@
#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_ #ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_ #define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
namespace content { namespace content {
class RenderFrameHost;
class WebContents; class WebContents;
} // namespace content } // namespace content
...@@ -28,13 +30,23 @@ class ProfileInteractionManager : public content::WebContentsObserver { ...@@ -28,13 +30,23 @@ class ProfileInteractionManager : public content::WebContentsObserver {
ProfileInteractionManager& operator=(const ProfileInteractionManager&) = ProfileInteractionManager& operator=(const ProfileInteractionManager&) =
delete; delete;
// content::WebContentsObserver:
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
// Invoked when the user has requested a reload of a page with blocked ads // Invoked when the user has requested a reload of a page with blocked ads
// (e.g., via an infobar). // (e.g., via an infobar).
void OnReloadRequested(); void OnReloadRequested();
// Invoked when an ads violation is triggered.
void OnAdsViolationTriggered(content::RenderFrameHost* rfh,
mojom::AdsViolation triggered_violation);
private: private:
// Unowned and must outlive this object. // Unowned and must outlive this object.
SubresourceFilterProfileContext* profile_context_ = nullptr; SubresourceFilterProfileContext* profile_context_ = nullptr;
bool ads_violation_triggered_for_last_committed_navigation_ = false;
}; };
} // namespace subresource_filter } // namespace subresource_filter
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment