Commit e8d16083 authored by Shivani Sharma's avatar Shivani Sharma Committed by Commit Bot

Propagation of ad tagging from parent frame to child frame.

This CL tags a subframe as an ad if its parent frame is tagged as well.
This extends the coverage of frames tagged as ads from just those that
match the ruleset to those that do not match but their parent frame is
tagged as an ad frame.

BUG: 807640
Change-Id: Ifee656298cdbe8bc16bcd24a16bc9a9905e2c2a3
Reviewed-on: https://chromium-review.googlesource.com/894542
Commit-Queue: Shivani Sharma <shivanisha@chromium.org>
Reviewed-by: default avatarJosh Karlin <jkarlin@chromium.org>
Reviewed-by: default avatarCharlie Harrison <csharrison@chromium.org>
Cr-Commit-Position: refs/heads/master@{#533323}
parent e4f4259c
...@@ -56,6 +56,7 @@ void ContentSubresourceFilterThrottleManager::OnSubresourceFilterGoingAway() { ...@@ -56,6 +56,7 @@ void ContentSubresourceFilterThrottleManager::OnSubresourceFilterGoingAway() {
void ContentSubresourceFilterThrottleManager::RenderFrameDeleted( void ContentSubresourceFilterThrottleManager::RenderFrameDeleted(
content::RenderFrameHost* frame_host) { content::RenderFrameHost* frame_host) {
activated_frame_hosts_.erase(frame_host); activated_frame_hosts_.erase(frame_host);
ad_frames_.erase(frame_host);
DestroyRulesetHandleIfNoLongerUsed(); DestroyRulesetHandleIfNoLongerUsed();
} }
...@@ -103,6 +104,9 @@ void ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation( ...@@ -103,6 +104,9 @@ void ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation(
content::RenderFrameHost* frame_host = content::RenderFrameHost* frame_host =
navigation_handle->GetRenderFrameHost(); navigation_handle->GetRenderFrameHost();
if (is_ad_subframe)
ad_frames_.insert(frame_host);
frame_host->Send(new SubresourceFilterMsg_ActivateForNextCommittedLoad( frame_host->Send(new SubresourceFilterMsg_ActivateForNextCommittedLoad(
frame_host->GetRoutingID(), filter->activation_state(), is_ad_subframe)); frame_host->GetRoutingID(), filter->activation_state(), is_ad_subframe));
} }
...@@ -216,11 +220,21 @@ void ContentSubresourceFilterThrottleManager::OnSubframeNavigationEvaluated( ...@@ -216,11 +220,21 @@ void ContentSubresourceFilterThrottleManager::OnSubframeNavigationEvaluated(
LoadPolicy load_policy) { LoadPolicy load_policy) {
DCHECK(!navigation_handle->IsInMainFrame()); DCHECK(!navigation_handle->IsInMainFrame());
auto it = ongoing_activation_throttles_.find(navigation_handle); auto it = ongoing_activation_throttles_.find(navigation_handle);
if (it != ongoing_activation_throttles_.end()) { if (it == ongoing_activation_throttles_.end())
// Note that is_ad_subframe is only relevant for return;
// LoadPolicy:WOULD_DISALLOW(dryrun mode), although also setting it for
// DISALLOW for completeness. // Note that is_ad_subframe is only relevant for
it->second.is_ad_subframe = load_policy != LoadPolicy::ALLOW; // LoadPolicy:WOULD_DISALLOW(dryrun mode), although also setting it for
// DISALLOW for completeness.
it->second.is_ad_subframe = load_policy != LoadPolicy::ALLOW;
// If this frame was not identified as an ad via ruleset matching, tag it
// based on whether its parent frame is an ad or not.
if (!it->second.is_ad_subframe) {
content::RenderFrameHost* parent_frame =
navigation_handle->GetParentFrame();
if (parent_frame && base::ContainsKey(ad_frames_, parent_frame))
it->second.is_ad_subframe = true;
} }
} }
...@@ -247,6 +261,11 @@ void ContentSubresourceFilterThrottleManager::MaybeAppendNavigationThrottles( ...@@ -247,6 +261,11 @@ void ContentSubresourceFilterThrottleManager::MaybeAppendNavigationThrottles(
} }
} }
bool ContentSubresourceFilterThrottleManager::IsFrameTaggedAsAdForTesting(
content::RenderFrameHost* frame_host) {
return base::ContainsKey(ad_frames_, frame_host);
}
std::unique_ptr<SubframeNavigationFilteringThrottle> std::unique_ptr<SubframeNavigationFilteringThrottle>
ContentSubresourceFilterThrottleManager:: ContentSubresourceFilterThrottleManager::
MaybeCreateSubframeNavigationFilteringThrottle( MaybeCreateSubframeNavigationFilteringThrottle(
......
...@@ -5,13 +5,15 @@ ...@@ -5,13 +5,15 @@
#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_SUBRESOURCE_FILTER_THROTTLE_MANAGER_H_ #ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_SUBRESOURCE_FILTER_THROTTLE_MANAGER_H_
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_SUBRESOURCE_FILTER_THROTTLE_MANAGER_H_ #define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_SUBRESOURCE_FILTER_THROTTLE_MANAGER_H_
#include <map>
#include <memory> #include <memory>
#include <unordered_map> #include <set>
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "base/stl_util.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer.h" #include "components/subresource_filter/content/browser/subresource_filter_observer.h"
#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h" #include "components/subresource_filter/content/browser/verified_ruleset_dealer.h"
#include "components/subresource_filter/core/common/activation_decision.h" #include "components/subresource_filter/core/common/activation_decision.h"
...@@ -84,6 +86,8 @@ class ContentSubresourceFilterThrottleManager ...@@ -84,6 +86,8 @@ class ContentSubresourceFilterThrottleManager
return ruleset_handle_.get(); return ruleset_handle_.get();
} }
bool IsFrameTaggedAsAdForTesting(content::RenderFrameHost* frame_host);
protected: protected:
// content::WebContentsObserver: // content::WebContentsObserver:
void RenderFrameDeleted(content::RenderFrameHost* frame_host) override; void RenderFrameDeleted(content::RenderFrameHost* frame_host) override;
...@@ -143,8 +147,8 @@ class ContentSubresourceFilterThrottleManager ...@@ -143,8 +147,8 @@ class ContentSubresourceFilterThrottleManager
// For each RenderFrameHost where the last committed load has subresource // For each RenderFrameHost where the last committed load has subresource
// filtering activated, owns the corresponding AsyncDocumentSubresourceFilter. // filtering activated, owns the corresponding AsyncDocumentSubresourceFilter.
// It is possible for a frame to have a null filter. // It is possible for a frame to have a null filter.
std::unordered_map<content::RenderFrameHost*, std::map<content::RenderFrameHost*,
std::unique_ptr<AsyncDocumentSubresourceFilter>> std::unique_ptr<AsyncDocumentSubresourceFilter>>
activated_frame_hosts_; activated_frame_hosts_;
// For each ongoing navigation that requires activation state computation, // For each ongoing navigation that requires activation state computation,
...@@ -157,9 +161,13 @@ class ContentSubresourceFilterThrottleManager ...@@ -157,9 +161,13 @@ class ContentSubresourceFilterThrottleManager
bool is_ad_subframe = false; bool is_ad_subframe = false;
}; };
std::unordered_map<content::NavigationHandle*, OngoingThrottleInfo> std::map<content::NavigationHandle*, OngoingThrottleInfo>
ongoing_activation_throttles_; ongoing_activation_throttles_;
// Set of frames that have been identified as ads, either through matching the
// ruleset or if their parent frame was an ad frame.
std::set<content::RenderFrameHost*> ad_frames_;
ScopedObserver<SubresourceFilterObserverManager, SubresourceFilterObserver> ScopedObserver<SubresourceFilterObserverManager, SubresourceFilterObserver>
scoped_observer_; scoped_observer_;
......
...@@ -745,6 +745,81 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, ...@@ -745,6 +745,81 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
true /* is_ad_subframe */); true /* is_ad_subframe */);
} }
TEST_P(ContentSubresourceFilterThrottleManagerTest,
DryRun_FrameTaggingAsAdPropagatesToChildFrame) {
NavigateAndCommitMainFrame(GURL(kTestURLWithDryRun));
ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
// A disallowed subframe navigation should not be filtered in dry-run mode.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::RenderFrameHost* child =
SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
EXPECT_TRUE(child);
// But it should still be activated.
ExpectActivationSignalForFrame(child, true /* expect_activation */,
true /* is_ad_subframe */);
EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAdForTesting(child));
// Create a subframe which is allowed as per ruleset but should still be
// tagged as ad because of its parent.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/allowed_by_ruleset.html"), child);
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::RenderFrameHost* grandchild =
SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
EXPECT_TRUE(grandchild);
ExpectActivationSignalForFrame(grandchild, true /* expect_activation */,
true /* is_ad_subframe */);
EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAdForTesting(grandchild));
// Verify that a 2nd level nested frame should also be tagged.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/great_grandchild_allowed_by_ruleset.html"),
child);
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::RenderFrameHost* greatGrandchild =
SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
EXPECT_TRUE(greatGrandchild);
ExpectActivationSignalForFrame(greatGrandchild, true /* expect_activation */,
true /* is_ad_subframe */);
EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAdForTesting(greatGrandchild));
EXPECT_EQ(0, disallowed_notification_count());
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
DryRun_AllowedsFrameNotTaggedAsAd) {
NavigateAndCommitMainFrame(GURL(kTestURLWithDryRun));
ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/allowed_by_ruleset.html"), main_rfh());
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::RenderFrameHost* child =
SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
EXPECT_TRUE(child);
ExpectActivationSignalForFrame(child, true /* expect_activation */,
false /* is_ad_subframe */);
EXPECT_FALSE(throttle_manager()->IsFrameTaggedAsAdForTesting(child));
// Create a subframe which is allowed as per ruleset and should not be tagged
// as ad because its parent is not tagged as well.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/also_allowed_by_ruleset.html"), child);
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::RenderFrameHost* grandchild =
SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
EXPECT_TRUE(grandchild);
ExpectActivationSignalForFrame(grandchild, true /* expect_activation */,
false /* is_ad_subframe */);
EXPECT_FALSE(throttle_manager()->IsFrameTaggedAsAdForTesting(grandchild));
EXPECT_EQ(0, disallowed_notification_count());
}
// TODO(csharrison): Make sure the following conditions are exercised in tests: // TODO(csharrison): Make sure the following conditions are exercised in tests:
// //
// - Synchronous navigations to about:blank. These hit issues with the // - Synchronous navigations to about:blank. These hit issues with the
......
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