chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/common/api/declarative_net_request.h"

#include <stddef.h>

#include <algorithm>
#include <functional>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_run_loop_timeout.h"
#include "base/test/test_timeouts.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/load_error_reporter.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/api/declarative_net_request/declarative_net_request_api.h"
#include "extensions/browser/api/declarative_net_request/file_backed_ruleset_source.h"
#include "extensions/browser/api/declarative_net_request/parse_info.h"
#include "extensions/browser/api/declarative_net_request/prefs_helper.h"
#include "extensions/browser/api/declarative_net_request/rule_counts.h"
#include "extensions/browser/api/declarative_net_request/rules_monitor_service.h"
#include "extensions/browser/api/declarative_net_request/ruleset_manager.h"
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
#include "extensions/browser/api/declarative_net_request/test_utils.h"
#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/api/declarative_net_request/constants.h"
#include "extensions/common/api/declarative_net_request/test_utils.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/file_util.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/url_pattern.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace extensions {
namespace declarative_net_request {
namespace {

constexpr char kJSONRulesFilename[] =;

constexpr char kSmallRegexFilter[] =;
constexpr char kLargeRegexFilter[] =;

constexpr char kId1[] =;
constexpr char kId2[] =;
constexpr char kId3[] =;
constexpr char kId4[] =;
constexpr char kDefaultRulesetID[] =;

dnr_api;

ElementsAreArray;
Field;
Pointee;
Property;
UnorderedElementsAre;
UnorderedElementsAreArray;

template <class T>
base::Value::List VectorToList(const std::vector<T>& values) {}

std::string GetErrorWithFilename(
    const std::string& error,
    const std::string& filename = kJSONRulesFilename) {}

InstallWarning GetLargeRegexWarning(
    int rule_id,
    const std::string& filename = kJSONRulesFilename) {}

// Returns the vector of install warnings, filtering out the one associated with
// a deprecated manifest version.
// TODO(crbug.com/40804030): Remove this method when the associated tests
// are updated to MV3.
std::vector<InstallWarning> GetFilteredInstallWarnings(
    const Extension& extension) {}

// Base test fixture to test indexing of rulesets.
class DeclarativeNetRequestUnittest : public DNRTestBase {};

// Fixture testing that declarative rules corresponding to the Declarative Net
// Request API are correctly indexed, for both packed and unpacked extensions.
// This only tests a single ruleset.
class SingleRulesetTest : public DeclarativeNetRequestUnittest {};

TEST_P(SingleRulesetTest, DuplicateResourceTypes) {}

TEST_P(SingleRulesetTest, EmptyRedirectRuleUrl) {}

TEST_P(SingleRulesetTest, InvalidRuleID) {}

TEST_P(SingleRulesetTest, InvalidRedirectRulePriority) {}

TEST_P(SingleRulesetTest, NoApplicableResourceTypes) {}

// Ensure that rules with both "domains" and "initiator_domains" conditions fail
// parsing.
TEST_P(SingleRulesetTest, DuplicateDomainsList) {}

// Ensure that rules with both "excluded_domains" and
// "excluded_initiator_domains" conditions fail parsing.
TEST_P(SingleRulesetTest, DuplicateExcludedDomainsList) {}

// Ensure that rules with an empty "domains" condition fail parsing.
TEST_P(SingleRulesetTest, EmptyDomainsList) {}

// Ensure that rules with an empty "initiator_domains" condition fail parsing.
TEST_P(SingleRulesetTest, EmptyInitiatorDomainsList) {}

// Ensure that rules with an empty "request_domains" condition fail parsing.
TEST_P(SingleRulesetTest, EmptyRequestDomainsList) {}

// Ensure that rules with a "domains" condition that contains non-ascii
// characters fail parsing.
TEST_P(SingleRulesetTest, NonAsciiDomainsList) {}

// Ensure that rules with a "excluded_domains" condition that contains non-ascii
// characters fail parsing.
TEST_P(SingleRulesetTest, NonAsciiExcludedDomainsList) {}

// Ensure that rules with a "initiator_domains" condition that contains
// non-ascii characters fail parsing.
TEST_P(SingleRulesetTest, NonAsciiInitiatorDomainsList) {}

// Ensure that rules with a "excluded_initiator_domains" condition that contains
// non-ascii characters fail parsing.
TEST_P(SingleRulesetTest, NonAsciiExcludedInitiatorDomainsList) {}

// Ensure that rules with a "request_domains" condition that contains non-ascii
// characters fail parsing.
TEST_P(SingleRulesetTest, NonAsciiRequestDomainsList) {}

// Ensure that rules with a "excluded_request_domains" condition that contains
// non-ascii characters fail parsing.
TEST_P(SingleRulesetTest, NonAsciiExcludedRequestDomainsList) {}

TEST_P(SingleRulesetTest, EmptyResourceTypeList) {}

TEST_P(SingleRulesetTest, EmptyURLFilter) {}

TEST_P(SingleRulesetTest, InvalidRedirectURL) {}

TEST_P(SingleRulesetTest, ListNotPassed) {}

TEST_P(SingleRulesetTest, DuplicateIDS) {}

// Ensure that we limit the number of parse failure warnings shown.
TEST_P(SingleRulesetTest, TooManyParseFailures) {}

// Ensures that rules which can't be parsed are ignored and cause an install
// warning.
TEST_P(SingleRulesetTest, InvalidJSONRules_StrongTypes) {}

// Ensures that rules which can't be parsed are ignored and cause an install
// warning.
TEST_P(SingleRulesetTest, InvalidJSONRules_Parsed) {}

// Ensure that regex rules which exceed the per rule memory limit are ignored
// and raise an install warning.
TEST_P(SingleRulesetTest, LargeRegexIgnored) {}

// Test an extension with both an error and an install warning.
TEST_P(SingleRulesetTest, WarningAndError) {}

// Ensure that we get an install warning on exceeding the regex rule count
// limit.
TEST_P(SingleRulesetTest, RegexRuleCountExceeded) {}

TEST_P(SingleRulesetTest, InvalidJSONFile) {}

TEST_P(SingleRulesetTest, EmptyRuleset) {}

TEST_P(SingleRulesetTest, AddSingleRule) {}

TEST_P(SingleRulesetTest, AddTwoRules) {}

// Test that we do not use an extension provided indexed ruleset.
TEST_P(SingleRulesetTest, ExtensionWithIndexedRuleset) {}

// Test for crbug.com/931967. Ensures that adding dynamic rules in the midst of
// an initial ruleset load (in response to OnExtensionLoaded) behaves
// predictably and doesn't DCHECK.
TEST_P(SingleRulesetTest, DynamicRulesetRace) {}

// Ensures that an updateEnabledRulesets call in the midst of an initial ruleset
// load (in response to OnExtensionLoaded) behaves predictably and doesn't
// DCHECK.
TEST_P(SingleRulesetTest, UpdateEnabledRulesetsRace) {}

// Tests updateSessionRules and getSessionRules extension function calls.
TEST_P(SingleRulesetTest, SessionRules) {}

// Ensure an error is raised when an extension adds a session-scoped regex rule
// which consumes more memory than allowed.
TEST_P(SingleRulesetTest, LargeRegexError_SessionRules) {}

// Ensure that we can add up to the |dnr_api::GUARANTEED_MINIMUM_STATIC_RULES| +
// |kMaxStaticRulesPerProfile| rules if the global rules feature is enabled.
TEST_P(SingleRulesetTest, RuleCountLimitMatched) {}

// Ensure that an extension's allocation will be kept or released when it is
// disabled based on the reason.
TEST_P(SingleRulesetTest, AllocationWhenDisabled) {}

// Ensure that we get an install warning on exceeding the rule count limit and
// that no rules are indexed.
TEST_P(SingleRulesetTest, RuleCountLimitExceeded) {}

// Tests that rule limits for both rule count and unsafe rule count are enforced
// for the dynamic and session rulesets of an extension.
TEST_P(SingleRulesetTest, DynamicAndSessionRuleLimits) {}

class SingleRulesetWithoutSafeRulesTest : public SingleRulesetTest {};

// TODO(crbug.com/40282671): This is just a sanity check that rule counts work
// as intended when the safe rules feature flag is turned off. Remove this test
// once feature is enabled and the feature flag is removed.
TEST_P(SingleRulesetWithoutSafeRulesTest, DynamicAndSessionRuleLimits) {}

// Tests that the regex rule limit is correctly shared between dynamic and
// session rulesets of an extension.
TEST_P(SingleRulesetTest, SharedDynamicAndSessionRegexRuleLimits) {}

// Test that getMatchedRules will return an error if an invalid tab id is
// specified.
TEST_P(SingleRulesetTest, GetMatchedRulesInvalidTabID) {}

// Tests that multiple static rulesets are correctly indexed.
class MultipleRulesetsTest : public DeclarativeNetRequestUnittest {};

// Tests an extension with multiple static rulesets.
TEST_P(MultipleRulesetsTest, Success) {}

// Tests an extension with no static rulesets.
TEST_P(MultipleRulesetsTest, ZeroRulesets) {}

// Tests an extension with multiple empty rulesets.
TEST_P(MultipleRulesetsTest, EmptyRulesets) {}

// Tests an extension with multiple static rulesets, with one of rulesets
// specifying an invalid rules file.
TEST_P(MultipleRulesetsTest, ListNotPassed) {}

// Tests an extension with multiple static rulesets with each ruleset generating
// some install warnings.
TEST_P(MultipleRulesetsTest, InstallWarnings) {}

TEST_P(MultipleRulesetsTest, EnabledRulesCount) {}

// Ensure that exceeding the regex rules limit across rulesets raises a warning.
TEST_P(MultipleRulesetsTest, RegexRuleCountExceeded) {}

TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_InvalidRulesetID) {}

// Ensure we correctly enforce the limit on the maximum number of static
// rulesets that can be enabled at a time
TEST_P(MultipleRulesetsTest,
       UpdateEnabledRulesets_EnabledRulesetCountExceeded) {}

TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_RegexRuleCountExceeded) {}

TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_InternalError) {}

TEST_P(MultipleRulesetsTest, UpdateAndGetEnabledRulesets_Success) {}

// Ensure that only rulesets which exceed the rules count limit will not have
// their rules indexed and will raise an install warning.
TEST_P(MultipleRulesetsTest, StaticRuleCountExceeded) {}

// Ensure that a ruleset which causes the extension to go over the global rule
// limit is correctly ignored.
TEST_P(MultipleRulesetsTest, RulesetIgnored) {}

// Ensure that the global rule count is counted correctly for multiple
// extensions.
TEST_P(MultipleRulesetsTest, MultipleExtensions) {}

// Ensure that the global rules limit is enforced correctly for multiple
// extensions.
TEST_P(MultipleRulesetsTest, MultipleExtensionsRuleLimitExceeded) {}

TEST_P(MultipleRulesetsTest, UpdateAndGetEnabledRulesets_RuleCountAllocation) {}

TEST_P(MultipleRulesetsTest, UpdateAndGetEnabledRulesets_RuleCountExceeded) {}

TEST_P(MultipleRulesetsTest,
       UpdateAndGetEnabledRulesets_KeepEnabledStaticRulesetsAfterReload) {}

// Tests attempting to disable rulesets when there are no rulesets active.
// Regression test for https://crbug.com/1354385.
TEST_P(MultipleRulesetsTest,
       UpdateAndGetEnabledRulesets_DisableRulesetsWhenEmptyEnabledRulesets) {}

// Test that getAvailableStaticRuleCount returns the correct number of rules an
// extension can still enable.
TEST_P(MultipleRulesetsTest, GetAvailableStaticRuleCount) {}

// Test to update disabled rule ids of static rulesets.
TEST_P(MultipleRulesetsTest, UpdateStaticRulesDisableAndEnableRules) {}

// Test UpdateStaticRules making no change.
TEST_P(MultipleRulesetsTest, UpdateStaticRulesMakingNoChange) {}

// Test to check UpdateStaticRules argument priority.
TEST_P(MultipleRulesetsTest, UpdateStaticRulesArgumentPriority) {}

// Test to check UpdateStaticRules error when rule limit exceeded.
TEST_P(MultipleRulesetsTest, UpdateStaticRulesErrorWhenRuleLimitExceeded) {}

// Test to check GetDisabledRuleIds error for invalid ruleset id.
TEST_P(MultipleRulesetsTest, GetDisabledStaticRuleIdsErrorForInvalidRuleset) {}

// Test the disabled rule ids when the extension is disabled and enabled.
TEST_P(MultipleRulesetsTest,
       KeepDisabledStaticRulesWhenExtensionDisabledAndEnabled) {}

// Test that an extension's allocation is reclaimed when unloaded in certain
// scenarios.
TEST_P(MultipleRulesetsTest, ReclaimAllocationOnUnload) {}

MultipleRulesetsTest_Unpacked;

// Test that reloading an unpacked extension is functionally identical to
// uninstalling then reinstalling it for the purpose of global rule allocation,
// and the allocation should reflect changes made to the extension.
TEST_P(MultipleRulesetsTest_Unpacked, UpdateAllocationOnReload) {}

INSTANTIATE_TEST_SUITE_P();

INSTANTIATE_TEST_SUITE_P();

INSTANTIATE_TEST_SUITE_P();

INSTANTIATE_TEST_SUITE_P();

}  // namespace
}  // namespace declarative_net_request
}  // namespace extensions