Index: components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc |
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc |
index 351ac5f2b4869de337739badd4f54a87b83fcaff..265d0752dc30a046b46adab4ed157dee3202c700 100644 |
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc |
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc |
@@ -4,21 +4,30 @@ |
#include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h" |
+#include <map> |
#include <memory> |
+#include <set> |
+#include <string> |
+#include <tuple> |
+#include <utility> |
#include "base/memory/ptr_util.h" |
#include "base/metrics/field_trial.h" |
+#include "base/run_loop.h" |
#include "base/test/histogram_tester.h" |
+#include "base/test/test_mock_time_task_runner.h" |
#include "components/safe_browsing_db/test_database_manager.h" |
#include "components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h" |
#include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" |
#include "components/subresource_filter/content/browser/subresource_filter_client.h" |
+#include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h" |
#include "components/subresource_filter/core/browser/subresource_filter_features.h" |
#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h" |
#include "components/subresource_filter/core/common/test_ruleset_creator.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/navigation_handle.h" |
#include "content/public/browser/web_contents_observer.h" |
+#include "content/public/test/cancelling_navigation_throttle.h" |
#include "content/public/test/navigation_simulator.h" |
#include "content/public/test/test_renderer_host.h" |
#include "testing/gmock/include/gmock/gmock.h" |
@@ -29,7 +38,7 @@ namespace subresource_filter { |
namespace { |
char kURL[] = "http://example.test/"; |
-char kRedirectURL[] = "http://foo.test/"; |
+char kRedirectURL[] = "http://redirect.test/"; |
// Names of navigation chain patterns histogram. |
const char kMatchesPatternHistogramNameSubresourceFilterSuffix[] = |
@@ -37,6 +46,10 @@ const char kMatchesPatternHistogramNameSubresourceFilterSuffix[] = |
"SubresourceFilterOnly"; |
const char kNavigationChainSizeSubresourceFilterSuffix[] = |
"SubresourceFilter.PageLoad.RedirectChainLength.SubresourceFilterOnly"; |
+const char kSafeBrowsingNavigationDelay[] = |
+ "SubresourceFilter.PageLoad.SafeBrowsingDelay"; |
+const char kSafeBrowsingCheckTime[] = |
+ "SubresourceFilter.SafeBrowsing.CheckTime"; |
// Human readable representation of expected redirect chain match patterns. |
// The explanations for the buckets given for the following redirect chain: |
@@ -76,7 +89,7 @@ class MockSubresourceFilterClient |
// called by the ThrottleManager. |
class TestForwardingNavigationThrottle : public content::NavigationThrottle { |
public: |
- TestForwardingNavigationThrottle(content::NavigationHandle* handle) |
+ explicit TestForwardingNavigationThrottle(content::NavigationHandle* handle) |
: content::NavigationThrottle(handle) {} |
~TestForwardingNavigationThrottle() override {} |
@@ -106,6 +119,8 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest |
void SetUp() override { |
content::RenderViewHostTestHarness::SetUp(); |
+ |
+ test_task_runner_ = new base::TestMockTimeTaskRunner(); |
scoped_feature_toggle_.reset( |
new testing::ScopedSubresourceFilterFeatureToggle( |
base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationLevelEnabled, |
@@ -120,6 +135,11 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest |
Observe(RenderViewHostTestHarness::web_contents()); |
} |
+ void TearDown() override { |
+ RunUntilIdle(); |
+ content::RenderViewHostTestHarness::TearDown(); |
+ } |
+ |
ContentSubresourceFilterDriverFactory* factory() { |
return ContentSubresourceFilterDriverFactory::FromWebContents( |
RenderViewHostTestHarness::web_contents()); |
@@ -129,30 +149,54 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest |
void DidStartNavigation( |
content::NavigationHandle* navigation_handle) override { |
ASSERT_TRUE(navigation_handle->IsInMainFrame()); |
- navigation_handle_ = navigation_handle; |
navigation_handle->RegisterThrottleForTesting( |
base::MakeUnique<SubresourceFilterSafeBrowsingActivationThrottle>( |
- navigation_handle, fake_safe_browsing_database_)); |
+ navigation_handle, test_task_runner_, |
+ fake_safe_browsing_database_)); |
navigation_handle->RegisterThrottleForTesting( |
base::MakeUnique<TestForwardingNavigationThrottle>(navigation_handle)); |
} |
- void SimulateStartAndExpectProceed() { |
+ content::NavigationThrottle::ThrottleCheckResult SimulateStart() { |
navigation_simulator_->Start(); |
- EXPECT_EQ(content::NavigationThrottle::PROCEED, |
- navigation_simulator_->GetLastThrottleCheckResult()); |
+ auto result = navigation_simulator_->GetLastThrottleCheckResult(); |
+ if (result == content::NavigationThrottle::CANCEL) |
+ navigation_simulator_.reset(); |
+ return result; |
} |
- void SimulateRedirectAndExpectProceed(const GURL& new_url) { |
+ content::NavigationThrottle::ThrottleCheckResult SimulateRedirect( |
+ const GURL& new_url) { |
navigation_simulator_->Redirect(new_url); |
- EXPECT_EQ(content::NavigationThrottle::PROCEED, |
- navigation_simulator_->GetLastThrottleCheckResult()); |
+ auto result = navigation_simulator_->GetLastThrottleCheckResult(); |
+ if (result == content::NavigationThrottle::CANCEL) |
+ navigation_simulator_.reset(); |
+ return result; |
} |
- void SimulateCommitAndExpectProceed() { |
+ content::NavigationThrottle::ThrottleCheckResult SimulateCommit() { |
+ // Need to post a task to flush the IO thread because calling Commit() |
+ // blocks until the throttle checks are complete. |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&base::TestMockTimeTaskRunner::RunUntilIdle, |
+ base::Unretained(test_task_runner_.get()))); |
navigation_simulator_->Commit(); |
- EXPECT_EQ(content::NavigationThrottle::PROCEED, |
- navigation_simulator_->GetLastThrottleCheckResult()); |
+ auto result = navigation_simulator_->GetLastThrottleCheckResult(); |
+ if (result == content::NavigationThrottle::CANCEL) |
+ navigation_simulator_.reset(); |
+ return result; |
+ } |
+ |
+ void SimulateStartAndExpectProceed() { |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, SimulateStart()); |
+ } |
+ |
+ void SimulateRedirectAndExpectProceed(const GURL& new_url) { |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, SimulateRedirect(new_url)); |
+ } |
+ |
+ void SimulateCommitAndExpectProceed() { |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, SimulateCommit()); |
} |
void CreateTestNavigationForMainFrame(const GURL& first_url) { |
@@ -168,20 +212,64 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest |
void SimulateTimeout() { fake_safe_browsing_database_->SimulateTimeout(); } |
+ void RunUntilIdle() { |
+ test_task_runner_->RunUntilIdle(); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
const base::HistogramTester& tester() const { return tester_; } |
+ base::TestMockTimeTaskRunner* test_task_runner() const { |
+ return test_task_runner_.get(); |
+ } |
+ |
private: |
base::FieldTrialList field_trial_list_; |
std::unique_ptr<testing::ScopedSubresourceFilterFeatureToggle> |
scoped_feature_toggle_; |
+ scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; |
std::unique_ptr<content::NavigationSimulator> navigation_simulator_; |
scoped_refptr<FakeSafeBrowsingDatabaseManager> fake_safe_browsing_database_; |
base::HistogramTester tester_; |
- content::NavigationHandle* navigation_handle_; |
DISALLOW_COPY_AND_ASSIGN(SubresourceFilterSafeBrowsingActivationThrottleTest); |
}; |
+class SubresourceFilterSafeBrowsingActivationThrottleTestWithCancelling |
+ : public SubresourceFilterSafeBrowsingActivationThrottleTest, |
+ public ::testing::WithParamInterface< |
+ std::tuple<content::CancellingNavigationThrottle::CancelTime, |
+ content::CancellingNavigationThrottle::ResultSynchrony>> { |
+ public: |
+ SubresourceFilterSafeBrowsingActivationThrottleTestWithCancelling() {} |
+ ~SubresourceFilterSafeBrowsingActivationThrottleTestWithCancelling() |
+ override {} |
+ |
+ void DidStartNavigation(content::NavigationHandle* handle) override { |
+ std::tie(cancel_time_, result_sync_) = GetParam(); |
+ handle->RegisterThrottleForTesting( |
+ base::MakeUnique<content::CancellingNavigationThrottle>( |
+ handle, cancel_time_, result_sync_)); |
+ SubresourceFilterSafeBrowsingActivationThrottleTest::DidStartNavigation( |
+ handle); |
+ } |
+ |
+ content::CancellingNavigationThrottle::CancelTime cancel_time() { |
+ return cancel_time_; |
+ } |
+ |
+ content::CancellingNavigationThrottle::ResultSynchrony result_sync() { |
+ return result_sync_; |
+ } |
+ |
+ private: |
+ content::CancellingNavigationThrottle::CancelTime cancel_time_; |
+ content::CancellingNavigationThrottle::ResultSynchrony result_sync_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN( |
+ SubresourceFilterSafeBrowsingActivationThrottleTestWithCancelling); |
+}; |
+ |
TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, |
ListNotMatched_NoActivation) { |
const GURL url(kURL); |
@@ -250,6 +338,16 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, |
SimulateTimeout(); |
CreateTestNavigationForMainFrame(url); |
SimulateStartAndExpectProceed(); |
+ |
+ // Flush the pending tasks on the IO thread, so the delayed task surely gets |
+ // posted. |
+ test_task_runner()->RunUntilIdle(); |
+ |
+ // Expect one delayed task, and fast forward time. |
+ base::TimeDelta expected_delay = |
+ SubresourceFilterSafeBrowsingClientRequest::kCheckURLTimeout; |
+ EXPECT_EQ(expected_delay, test_task_runner()->NextPendingTaskDelay()); |
+ test_task_runner()->FastForwardBy(expected_delay); |
SimulateCommitAndExpectProceed(); |
EXPECT_EQ(ContentSubresourceFilterDriverFactory::ActivationDecision:: |
ACTIVATION_LIST_NOT_MATCHED, |
@@ -257,11 +355,129 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, |
tester().ExpectTotalCount(kMatchesPatternHistogramNameSubresourceFilterSuffix, |
0); |
tester().ExpectTotalCount(kNavigationChainSizeSubresourceFilterSuffix, 0); |
+ tester().ExpectTotalCount(kSafeBrowsingNavigationDelay, 1); |
+ tester().ExpectTimeBucketCount(kSafeBrowsingNavigationDelay, |
+ base::TimeDelta::FromMilliseconds(0), 0); |
+ tester().ExpectTotalCount(kSafeBrowsingCheckTime, 1); |
+} |
+ |
+TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, |
+ ListMatchedOnStart_NoDelay) { |
+ const GURL url(kURL); |
+ ConfigureAsSubresourceFilterOnlyURL(url); |
+ CreateTestNavigationForMainFrame(url); |
+ SimulateStartAndExpectProceed(); |
+ |
+ // Get the database result back before commit. |
+ RunUntilIdle(); |
+ |
+ SimulateCommitAndExpectProceed(); |
+ EXPECT_EQ( |
+ ContentSubresourceFilterDriverFactory::ActivationDecision::ACTIVATED, |
+ factory()->GetActivationDecisionForLastCommittedPageLoad()); |
+ tester().ExpectUniqueSample( |
+ kMatchesPatternHistogramNameSubresourceFilterSuffix, NO_REDIRECTS_HIT, 1); |
+ tester().ExpectUniqueSample(kNavigationChainSizeSubresourceFilterSuffix, 1, |
+ 1); |
+ tester().ExpectTimeBucketCount(kSafeBrowsingNavigationDelay, |
+ base::TimeDelta::FromMilliseconds(0), 1); |
+} |
+ |
+TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, |
+ ListMatchedOnRedirect_NoDelay) { |
+ const GURL url(kURL); |
+ const GURL redirect_url(kRedirectURL); |
+ ConfigureAsSubresourceFilterOnlyURL(redirect_url); |
+ CreateTestNavigationForMainFrame(url); |
+ |
+ SimulateStartAndExpectProceed(); |
+ SimulateRedirectAndExpectProceed(redirect_url); |
+ |
+ // Get the database result back before commit. |
+ RunUntilIdle(); |
+ |
+ SimulateCommitAndExpectProceed(); |
+ EXPECT_EQ( |
+ ContentSubresourceFilterDriverFactory::ActivationDecision::ACTIVATED, |
+ factory()->GetActivationDecisionForLastCommittedPageLoad()); |
+ tester().ExpectUniqueSample( |
+ kMatchesPatternHistogramNameSubresourceFilterSuffix, F0M0L1, 1); |
+ tester().ExpectUniqueSample(kNavigationChainSizeSubresourceFilterSuffix, 2, |
+ 1); |
+ tester().ExpectTimeBucketCount(kSafeBrowsingNavigationDelay, |
+ base::TimeDelta::FromMilliseconds(0), 1); |
+ tester().ExpectTotalCount(kSafeBrowsingCheckTime, 2); |
+} |
+ |
+TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, |
+ ListMatchedOnStartWithRedirect_NoActivation) { |
+ const GURL url(kURL); |
+ const GURL redirect_url(kRedirectURL); |
+ ConfigureAsSubresourceFilterOnlyURL(url); |
+ CreateTestNavigationForMainFrame(url); |
+ |
+ // These two lines also test how the database client reacts to two requests |
+ // happening one after another. |
+ SimulateStartAndExpectProceed(); |
+ SimulateRedirectAndExpectProceed(redirect_url); |
+ |
+ // Get the database result back before commit. |
+ RunUntilIdle(); |
+ |
+ SimulateCommitAndExpectProceed(); |
+ EXPECT_EQ(ContentSubresourceFilterDriverFactory::ActivationDecision:: |
+ ACTIVATION_LIST_NOT_MATCHED, |
+ factory()->GetActivationDecisionForLastCommittedPageLoad()); |
+ tester().ExpectTotalCount(kMatchesPatternHistogramNameSubresourceFilterSuffix, |
+ 0); |
+ tester().ExpectTotalCount(kNavigationChainSizeSubresourceFilterSuffix, 0); |
+ tester().ExpectTimeBucketCount(kSafeBrowsingNavigationDelay, |
+ base::TimeDelta::FromMilliseconds(0), 1); |
+} |
+ |
+TEST_P(SubresourceFilterSafeBrowsingActivationThrottleTestWithCancelling, |
+ Cancel) { |
+ const GURL url(kURL); |
+ SCOPED_TRACE(::testing::Message() << "CancelTime: " << cancel_time() |
+ << " ResultSynchrony: " << result_sync()); |
+ ConfigureAsSubresourceFilterOnlyURL(url); |
+ CreateTestNavigationForMainFrame(url); |
+ |
+ content::NavigationThrottle::ThrottleCheckResult result = SimulateStart(); |
+ if (cancel_time() == |
+ content::CancellingNavigationThrottle::WILL_START_REQUEST) { |
+ EXPECT_EQ(content::NavigationThrottle::CANCEL, result); |
+ tester().ExpectTotalCount(kSafeBrowsingNavigationDelay, 0); |
+ return; |
+ } |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, result); |
+ |
+ result = SimulateRedirect(GURL(kRedirectURL)); |
+ if (cancel_time() == |
+ content::CancellingNavigationThrottle::WILL_REDIRECT_REQUEST) { |
+ EXPECT_EQ(content::NavigationThrottle::CANCEL, result); |
+ tester().ExpectTotalCount(kSafeBrowsingNavigationDelay, 0); |
+ return; |
+ } |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, result); |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ result = SimulateCommit(); |
+ EXPECT_EQ(content::NavigationThrottle::CANCEL, result); |
+ tester().ExpectTotalCount(kSafeBrowsingNavigationDelay, 0); |
} |
-// TODO(melandory): Once non-defering check in WillStart is implemented add one |
-// more test that destroys the Navigation along with corresponding throttles |
-// while the SB check is pending? (To be run by ASAN bots to ensure |
-// no use-after-free.) |
+INSTANTIATE_TEST_CASE_P( |
+ CancelMethod, |
+ SubresourceFilterSafeBrowsingActivationThrottleTestWithCancelling, |
+ ::testing::Combine( |
+ ::testing::Values( |
+ content::CancellingNavigationThrottle::WILL_START_REQUEST, |
+ content::CancellingNavigationThrottle::WILL_REDIRECT_REQUEST, |
+ content::CancellingNavigationThrottle::WILL_PROCESS_RESPONSE), |
+ ::testing::Values( |
+ content::CancellingNavigationThrottle::SYNCHRONOUS, |
+ content::CancellingNavigationThrottle::ASYNCHRONOUS))); |
} // namespace subresource_filter |