// Copyright (c) 2012 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 "chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.h" #include "base/bind.h" #include "base/macros.h" #include "base/test/values_test_util.h" #include "chrome/browser/extensions/api/declarative_content/content_predicate.h" #include "chrome/browser/extensions/api/declarative_content/content_predicate_evaluator.h" #include "chrome/browser/extensions/test_extension_environment.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/web_contents.h" #include "content/public/common/frame_navigate_params.h" #include "extensions/common/extension.h" #include "testing/gtest/include/gtest/gtest.h" namespace extensions { namespace { class TestPredicateEvaluator; class TestPredicate : public ContentPredicate { public: explicit TestPredicate(ContentPredicateEvaluator* evaluator) : evaluator_(evaluator) { } ContentPredicateEvaluator* GetEvaluator() const override { return evaluator_; } private: ContentPredicateEvaluator* evaluator_; DISALLOW_COPY_AND_ASSIGN(TestPredicate); }; class TestPredicateEvaluator : public ContentPredicateEvaluator { public: explicit TestPredicateEvaluator(ContentPredicateEvaluator::Delegate* delegate) : delegate_(delegate), contents_for_next_operation_evaluation_(nullptr), next_evaluation_result_(false) { } std::string GetPredicateApiAttributeName() const override { return "test_predicate"; } scoped_ptr<const ContentPredicate> CreatePredicate( const Extension* extension, const base::Value& value, std::string* error) override { RequestEvaluationIfSpecified(); return make_scoped_ptr(new TestPredicate(this)); } void TrackPredicates( const std::map<const void*, std::vector<const ContentPredicate*>>& predicates) override { RequestEvaluationIfSpecified(); } void StopTrackingPredicates( const std::vector<const void*>& predicate_groups) override { RequestEvaluationIfSpecified(); } void TrackForWebContents(content::WebContents* contents) override { RequestEvaluationIfSpecified(); } void OnWebContentsNavigation( content::WebContents* contents, const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) override { RequestEvaluationIfSpecified(); } bool EvaluatePredicate(const ContentPredicate* predicate, content::WebContents* tab) const override { bool result = next_evaluation_result_; next_evaluation_result_ = false; return result; } void RequestImmediateEvaluation(content::WebContents* contents, bool evaluation_result) { next_evaluation_result_ = evaluation_result; delegate_->RequestEvaluation(contents); } void RequestEvaluationOnNextOperation(content::WebContents* contents, bool evaluation_result) { contents_for_next_operation_evaluation_ = contents; next_evaluation_result_ = evaluation_result; } private: void RequestEvaluationIfSpecified() { if (contents_for_next_operation_evaluation_) delegate_->RequestEvaluation(contents_for_next_operation_evaluation_); contents_for_next_operation_evaluation_ = nullptr; } ContentPredicateEvaluator::Delegate* delegate_; content::WebContents* contents_for_next_operation_evaluation_; mutable bool next_evaluation_result_; DISALLOW_COPY_AND_ASSIGN(TestPredicateEvaluator); }; // Create the test evaluator and set |evaluator| to its pointer. std::vector<scoped_ptr<ContentPredicateEvaluator>> CreateTestEvaluator( TestPredicateEvaluator** evaluator, ContentPredicateEvaluator::Delegate* delegate) { std::vector<scoped_ptr<ContentPredicateEvaluator>> evaluators; *evaluator = new TestPredicateEvaluator(delegate); evaluators.push_back(scoped_ptr<ContentPredicateEvaluator>(*evaluator)); return evaluators; } } // namespace class DeclarativeChromeContentRulesRegistryTest : public testing::Test { public: DeclarativeChromeContentRulesRegistryTest() {} protected: TestExtensionEnvironment* env() { return &env_; } private: TestExtensionEnvironment env_; DISALLOW_COPY_AND_ASSIGN(DeclarativeChromeContentRulesRegistryTest); }; TEST_F(DeclarativeChromeContentRulesRegistryTest, ActiveRulesDoesntGrow) { TestPredicateEvaluator* evaluator = nullptr; scoped_refptr<ChromeContentRulesRegistry> registry( new ChromeContentRulesRegistry(env()->profile(), nullptr, base::Bind(&CreateTestEvaluator, &evaluator))); EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting()); scoped_ptr<content::WebContents> tab = env()->MakeTab(); registry->MonitorWebContentsForRuleEvaluation(tab.get()); registry->DidNavigateMainFrame(tab.get(), content::LoadCommittedDetails(), content::FrameNavigateParams()); EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting()); // Add a rule. linked_ptr<api::events::Rule> rule(new api::events::Rule); api::events::Rule::Populate( *base::test::ParseJson( "{\n" " \"id\": \"rule1\",\n" " \"priority\": 100,\n" " \"conditions\": [\n" " {\n" " \"instanceType\": \"declarativeContent.PageStateMatcher\",\n" " \"test_predicate\": []\n" " }],\n" " \"actions\": [\n" " { \"instanceType\": \"declarativeContent.ShowPageAction\" }\n" " ]\n" "}"), rule.get()); std::vector<linked_ptr<api::events::Rule>> rules; rules.push_back(rule); const Extension* extension = env()->MakeExtension(*base::test::ParseJson( "{\"page_action\": {}}")); registry->AddRulesImpl(extension->id(), rules); registry->DidNavigateMainFrame(tab.get(), content::LoadCommittedDetails(), content::FrameNavigateParams()); EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting()); evaluator->RequestImmediateEvaluation(tab.get(), true); EXPECT_EQ(1u, registry->GetActiveRulesCountForTesting()); // Closing the tab should erase its entry from active_rules_. tab.reset(); EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting()); tab = env()->MakeTab(); registry->MonitorWebContentsForRuleEvaluation(tab.get()); evaluator->RequestImmediateEvaluation(tab.get(), true); EXPECT_EQ(1u, registry->GetActiveRulesCountForTesting()); evaluator->RequestEvaluationOnNextOperation(tab.get(), false); registry->DidNavigateMainFrame(tab.get(), content::LoadCommittedDetails(), content::FrameNavigateParams()); EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting()); } } // namespace extensions