Index: components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc |
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f310d6ecf746e256aa232a77e92c5a4534ac108a |
--- /dev/null |
+++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc |
@@ -0,0 +1,323 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h" |
+ |
+#include <memory> |
+#include <utility> |
+ |
+#include "base/callback.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/optional.h" |
+#include "base/run_loop.h" |
+#include "base/test/test_simple_task_runner.h" |
+#include "components/subresource_filter/content/browser/async_document_subresource_filter.h" |
+#include "components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h" |
+#include "components/subresource_filter/core/common/activation_level.h" |
+#include "components/subresource_filter/core/common/activation_state.h" |
+#include "components/subresource_filter/core/common/proto/rules.pb.h" |
+#include "components/subresource_filter/core/common/test_ruleset_creator.h" |
+#include "components/subresource_filter/core/common/test_ruleset_utils.h" |
+#include "content/public/browser/navigation_handle.h" |
+#include "content/public/browser/web_contents_observer.h" |
+#include "content/public/common/referrer.h" |
engedy
2017/03/10 10:56:57
nit: Unused?
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+#include "content/public/test/navigation_simulator.h" |
+#include "content/public/test/test_renderer_host.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace subresource_filter { |
+ |
+class ActivationStateComputingNavigationThrottleTest |
+ : public content::RenderViewHostTestHarness, |
+ public content::WebContentsObserver { |
+ public: |
+ ActivationStateComputingNavigationThrottleTest() {} |
+ ~ActivationStateComputingNavigationThrottleTest() override {} |
+ |
+ void SetUp() override { |
+ content::RenderViewHostTestHarness::SetUp(); |
+ NavigateAndCommit(GURL("https://example.first")); |
+ InitializeRuleset(); |
+ Observe(RenderViewHostTestHarness::web_contents()); |
+ } |
+ |
+ void TearDown() override { |
+ async_filter_.reset(); |
+ ruleset_handle_.reset(); |
+ dealer_handle_.reset(); |
+ RunUntilIdle(); |
+ content::RenderViewHostTestHarness::TearDown(); |
+ } |
+ |
+ // content::WebContentsObserver: |
engedy
2017/03/10 10:56:57
nit: Could you please move these further down into
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+ void DidStartNavigation( |
+ content::NavigationHandle* navigation_handle) override { |
+ std::unique_ptr<ActivationStateComputingNavigationThrottle> throttle = |
+ navigation_handle->IsInMainFrame() |
+ ? ActivationStateComputingNavigationThrottle::CreateForMainFrame( |
+ navigation_handle) |
+ : ActivationStateComputingNavigationThrottle::CreateForSubframe( |
+ navigation_handle, ruleset_handle_.get(), |
+ parent_activation_state_.value()); |
+ test_throttle_ = throttle.get(); |
+ navigation_handle->RegisterThrottleForTesting(std::move(throttle)); |
+ } |
+ |
+ void ReadyToCommitNavigation( |
+ content::NavigationHandle* navigation_handle) override { |
+ if (!test_throttle_) |
+ return; |
+ ASSERT_EQ(navigation_handle, test_throttle_->navigation_handle()); |
+ last_activation_state_ = test_throttle_->GetActivationState(); |
+ if (last_activation_state_.value().activation_level == |
+ ActivationLevel::DISABLED) { |
+ EXPECT_FALSE(test_throttle_->ReleaseFilter()); |
+ } else { |
+ EXPECT_TRUE(test_throttle_->ReleaseFilter()); |
+ } |
+ test_throttle_ = nullptr; |
+ } |
+ |
+ void InitializeRuleset() { |
+ std::vector<proto::UrlRule> rules; |
+ rules.push_back(testing::CreateWhitelistRuleForDocument( |
+ "whitelist.com", proto::ACTIVATION_TYPE_DOCUMENT, {"parent.com"})); |
engedy
2017/03/10 10:56:57
nit: Let's call these whitelisted.com and allow-ch
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+ ASSERT_NO_FATAL_FAILURE(test_ruleset_creator_.CreateRulesetWithRules( |
+ rules, &test_ruleset_pair_)); |
+ |
+ // Make the blocking task runner run on the current task runner for the |
+ // tests, to ensure that the NavigationSimulator properly runs all necessary |
+ // tasks while waiting for throttle checks to finish. |
+ dealer_handle_ = base::MakeUnique<VerifiedRulesetDealer::Handle>( |
+ base::MessageLoop::current()->task_runner()); |
+ dealer_handle_->SetRulesetFile( |
+ testing::TestRuleset::Open(test_ruleset_pair_.indexed)); |
+ ruleset_handle_ = |
+ base::MakeUnique<VerifiedRuleset::Handle>(dealer_handle_.get()); |
+ } |
+ void InitializeDocumentSubresourceFilter(const GURL& document_url) { |
+ NavigateAndCommit(document_url); |
engedy
2017/03/10 10:56:57
Apart from this line, this function has no effect
Charlie Harrison
2017/03/10 17:12:47
Oops, sorry about that. I've reworked the tests to
|
+ |
+ testing::TestActivationStateCallbackReceiver activation_state; |
+ async_filter_ = base::MakeUnique<AsyncDocumentSubresourceFilter>( |
+ ruleset_handle_.get(), |
+ AsyncDocumentSubresourceFilter::InitializationParams( |
+ document_url, ActivationLevel::ENABLED, |
+ false /* measure_performance */), |
+ activation_state.GetCallback(), base::OnceClosure()); |
+ RunUntilIdle(); |
+ activation_state.ExpectReceivedOnce( |
+ ActivationState(ActivationLevel::ENABLED)); |
+ } |
+ |
+ void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } |
+ |
+ void CreateTestNavigationForMainFrame(const GURL& first_url) { |
+ navigation_simulator_ = |
+ content::NavigationSimulator::CreateRendererInitiated(first_url, |
+ main_rfh()); |
+ } |
+ |
+ void CreateSubframeAndInitTestNavigation( |
+ const GURL& first_url, |
+ const ActivationState& parent_activation_state) { |
+ parent_activation_state_ = parent_activation_state; |
+ content::RenderFrameHost* navigating_subframe = |
+ content::RenderFrameHostTester::For(main_rfh()) |
+ ->AppendChild("subframe"); |
+ navigation_simulator_ = |
+ content::NavigationSimulator::CreateRendererInitiated( |
+ first_url, navigating_subframe); |
+ } |
+ |
+ void SimulateStartAndExpectToProceed() { |
+ ASSERT_TRUE(navigation_simulator_); |
+ navigation_simulator_->Start(); |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, |
+ navigation_simulator_->GetLastThrottleCheckResult()); |
+ } |
+ |
+ void SimulateRedirectAndExpectToProceed(const GURL& new_url) { |
+ navigation_simulator_->Redirect(new_url); |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, |
+ navigation_simulator_->GetLastThrottleCheckResult()); |
+ } |
+ |
+ void SimulateCommitAndExpectToProceed() { |
+ navigation_simulator_->Commit(); |
+ EXPECT_EQ(content::NavigationThrottle::PROCEED, |
+ navigation_simulator_->GetLastThrottleCheckResult()); |
+ } |
+ |
+ void NotifyPageActivation(ActivationState state) { |
+ test_throttle_->NotifyPageActivationWithRuleset( |
+ state.activation_level == ActivationLevel::DISABLED |
+ ? nullptr |
+ : ruleset_handle_.get(), |
+ state); |
+ } |
+ |
+ const ActivationState& last_activation_state() { |
+ return last_activation_state_.value(); |
engedy
2017/03/10 10:56:57
nit: This essentially EXPECT's that las_ will have
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+ } |
+ |
+ private: |
+ testing::TestRulesetCreator test_ruleset_creator_; |
+ testing::TestRulesetPair test_ruleset_pair_; |
+ |
+ std::unique_ptr<VerifiedRulesetDealer::Handle> dealer_handle_; |
+ std::unique_ptr<VerifiedRuleset::Handle> ruleset_handle_; |
+ |
+ std::unique_ptr<AsyncDocumentSubresourceFilter> async_filter_; |
+ |
+ std::unique_ptr<content::NavigationSimulator> navigation_simulator_; |
+ |
+ // Owned by the current navigation. |
+ ActivationStateComputingNavigationThrottle* test_throttle_; |
+ base::Optional<ActivationState> last_activation_state_; |
+ base::Optional<ActivationState> parent_activation_state_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ActivationStateComputingNavigationThrottleTest); |
engedy
2017/03/10 10:56:57
#include "base/macros.h"
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+}; |
+ |
+// Main frame tests |
+TEST_F(ActivationStateComputingNavigationThrottleTest, ActivateMainFrame) { |
engedy
2017/03/10 11:53:41
optional nit: If we had two test fixtures, Activat
Charlie Harrison
2017/03/10 17:12:47
Done. I also rewrote some of the tests to fit the
|
+ CreateTestNavigationForMainFrame(GURL("http://example.test/activate.html")); |
+ SimulateStartAndExpectToProceed(); |
+ |
+ NotifyPageActivation(ActivationState(ActivationLevel::ENABLED)); |
engedy
2017/03/10 10:56:57
nit for follow-up CL: Ultimately we should have a
Charlie Harrison
2017/03/10 17:12:47
Would this be before WillStartRequest but after Di
engedy
2017/03/10 18:33:42
Exactly, the overall navigation will be in the Wil
|
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level); |
+ EXPECT_FALSE(state.filtering_disabled_for_document); |
+} |
+ |
+TEST_F(ActivationStateComputingNavigationThrottleTest, |
+ DoNotActivateMainFrameForInactivePage) { |
+ CreateTestNavigationForMainFrame(GURL("http://example.test/inactivate.html")); |
engedy
2017/03/10 10:56:57
nit: Let's remove the paths in all these URL, thei
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+ SimulateStartAndExpectToProceed(); |
+ SimulateRedirectAndExpectToProceed( |
+ GURL("http://example.test/inactivate.html?v=1")); |
+ |
+ // Never send NotifyPageActivation. |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_EQ(ActivationLevel::DISABLED, state.activation_level); |
+} |
+ |
+TEST_F(ActivationStateComputingNavigationThrottleTest, |
+ DoNotActivateMainFrameForInactivePage2) { |
+ CreateTestNavigationForMainFrame(GURL("http://example.test/inactivate.html")); |
+ SimulateStartAndExpectToProceed(); |
+ SimulateRedirectAndExpectToProceed( |
+ GURL("http://example.test/inactivate.html?v=1")); |
+ |
+ // Notify that the page level state is explicitly disabled. Should be |
engedy
2017/03/10 10:56:57
nit: s/level state/(level) activation/
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+ // equivalent to not sending the message at all. |
+ NotifyPageActivation(ActivationState(ActivationLevel::DISABLED)); |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_EQ(ActivationLevel::DISABLED, state.activation_level); |
+} |
+ |
+TEST_F(ActivationStateComputingNavigationThrottleTest, |
engedy
2017/03/10 10:56:57
Let's also have a test where the main frame is act
engedy
2017/03/10 10:56:57
In addition to (or instead of) this test, let's ha
Charlie Harrison
2017/03/10 17:12:46
Done.
Charlie Harrison
2017/03/10 17:12:46
Done.
|
+ ActivateMainFrameWhitelistedSubframe) { |
engedy
2017/03/10 10:56:57
nit: s/ActivateMainFrameWhitelistedSubframe/MainFr
Charlie Harrison
2017/03/10 17:12:46
Done.
|
+ InitializeDocumentSubresourceFilter(GURL("http://parent.com/")); |
+ // Not really a child frame, so whitelist should not apply. |
+ CreateTestNavigationForMainFrame(GURL("http://whitelist.com/")); |
+ SimulateStartAndExpectToProceed(); |
+ |
+ // Main frames will usually have their "parent" activation state set right |
+ // before WillProcessResponse. |
+ NotifyPageActivation(ActivationState(ActivationLevel::ENABLED)); |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_FALSE(state.filtering_disabled_for_document); |
+ EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level); |
+} |
+ |
+// Subframe tests |
+TEST_F(ActivationStateComputingNavigationThrottleTest, ActivateSubframe) { |
+ InitializeDocumentSubresourceFilter(GURL("http://example.test")); |
+ CreateSubframeAndInitTestNavigation( |
+ GURL("http://example.test/activate.html"), |
+ ActivationState(ActivationLevel::ENABLED)); |
+ SimulateStartAndExpectToProceed(); |
+ SimulateRedirectAndExpectToProceed( |
+ GURL("http://example.test/activate.html?v=1")); |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level); |
+ EXPECT_FALSE(state.filtering_disabled_for_document); |
+} |
+ |
+TEST_F(ActivationStateComputingNavigationThrottleTest, |
+ DoNotActivateWhitelistedSubframe) { |
engedy
2017/03/10 10:56:57
We should also a version to verify that proto::ACT
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+ InitializeDocumentSubresourceFilter(GURL("http://parent.com/")); |
+ CreateSubframeAndInitTestNavigation( |
+ GURL("http://whitelist.com/"), ActivationState(ActivationLevel::ENABLED)); |
+ SimulateStartAndExpectToProceed(); |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_TRUE(state.filtering_disabled_for_document); |
+ EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level); |
+} |
+ |
+TEST_F(ActivationStateComputingNavigationThrottleTest, |
+ EnsureDryRunIsPropagated) { |
engedy
2017/03/10 10:56:57
We should also have a version to verify that page
Charlie Harrison
2017/03/10 17:12:47
This test now verifies that with the refactoring I
|
+ InitializeDocumentSubresourceFilter(GURL("http://example.test")); |
+ CreateSubframeAndInitTestNavigation(GURL("http://example.test/activate.html"), |
+ ActivationState(ActivationLevel::DRYRUN)); |
+ SimulateStartAndExpectToProceed(); |
+ SimulateRedirectAndExpectToProceed( |
+ GURL("http://example.test/activate.html?v=1")); |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_EQ(ActivationLevel::DRYRUN, state.activation_level); |
engedy
2017/03/10 10:56:57
nit:
EXPECT_FALSE(state.filtering_disabled_for_do
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+} |
+ |
+TEST_F(ActivationStateComputingNavigationThrottleTest, |
+ DisabledStatePropagatedDocument) { |
+ InitializeDocumentSubresourceFilter(GURL("http://example.test")); |
+ ActivationState parent_activation(ActivationLevel::ENABLED); |
+ parent_activation.filtering_disabled_for_document = true; |
+ CreateSubframeAndInitTestNavigation(GURL("http://example.test/activate.html"), |
+ parent_activation); |
+ SimulateStartAndExpectToProceed(); |
+ SimulateRedirectAndExpectToProceed( |
+ GURL("http://example.test/activate.html?v=1")); |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level); |
+ EXPECT_TRUE(state.filtering_disabled_for_document); |
+ EXPECT_FALSE(state.generic_blocking_rules_disabled); |
+} |
+ |
+TEST_F(ActivationStateComputingNavigationThrottleTest, |
+ DisabledStatePropagatedGeneric) { |
engedy
2017/03/10 10:56:57
We should have a test (a new one or extend an exis
Charlie Harrison
2017/03/10 17:12:47
Done.
|
+ InitializeDocumentSubresourceFilter(GURL("http://example.test")); |
+ ActivationState parent_activation(ActivationLevel::ENABLED); |
+ parent_activation.generic_blocking_rules_disabled = true; |
+ CreateSubframeAndInitTestNavigation(GURL("http://example.test/activate.html"), |
+ parent_activation); |
+ SimulateStartAndExpectToProceed(); |
+ SimulateRedirectAndExpectToProceed( |
+ GURL("http://example.test/activate.html?v=1")); |
+ SimulateCommitAndExpectToProceed(); |
+ |
+ ActivationState state = last_activation_state(); |
+ EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level); |
+ EXPECT_FALSE(state.filtering_disabled_for_document); |
+ EXPECT_TRUE(state.generic_blocking_rules_disabled); |
+} |
+ |
+} // namespace subresource_filter |