blob: 025aeeb0087a293fd8c38daf8b63dbb60ea59d61 [file] [log] [blame]
// 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.
#ifndef EXTENSIONS_COMMON_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_
#define EXTENSIONS_COMMON_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_
#include <optional>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/values.h"
#include "extensions/common/api/declarative_net_request/constants.h"
#include "extensions/common/url_pattern.h"
namespace extensions::declarative_net_request {
inline constexpr char kManifestSandboxPageFilepath[] = "manifest_sandbox.html";
struct DictionarySource {
DictionarySource() = default;
virtual ~DictionarySource() = default;
virtual base::Value::Dict ToValue() const = 0;
};
// Helper structs to simplify building base::Values which can later be used to
// serialize to JSON. The generated implementation for the JSON rules schema is
// not used since it's not flexible enough to generate the base::Value/JSON we
// want for tests.
struct TestHeaderCondition : public DictionarySource {
TestHeaderCondition(std::string header,
std::vector<std::string> values,
std::vector<std::string> excluded_values);
~TestHeaderCondition() override;
TestHeaderCondition(const TestHeaderCondition&);
TestHeaderCondition& operator=(const TestHeaderCondition&);
std::optional<std::string> header;
std::optional<std::vector<std::string>> values;
std::optional<std::vector<std::string>> excluded_values;
base::Value::Dict ToValue() const override;
};
struct TestRuleCondition : public DictionarySource {
TestRuleCondition();
~TestRuleCondition() override;
TestRuleCondition(const TestRuleCondition&);
TestRuleCondition& operator=(const TestRuleCondition&);
std::optional<std::string> url_filter;
std::optional<std::string> regex_filter;
std::optional<bool> is_url_filter_case_sensitive;
std::optional<std::vector<std::string>> domains;
std::optional<std::vector<std::string>> excluded_domains;
std::optional<std::vector<std::string>> initiator_domains;
std::optional<std::vector<std::string>> excluded_initiator_domains;
std::optional<std::vector<std::string>> request_domains;
std::optional<std::vector<std::string>> excluded_request_domains;
std::optional<std::vector<std::string>> top_domains;
std::optional<std::vector<std::string>> excluded_top_domains;
std::optional<std::vector<std::string>> request_methods;
std::optional<std::vector<std::string>> excluded_request_methods;
std::optional<std::vector<std::string>> resource_types;
std::optional<std::vector<std::string>> excluded_resource_types;
std::optional<std::vector<int>> tab_ids;
std::optional<std::vector<int>> excluded_tab_ids;
std::optional<std::string> domain_type;
std::optional<std::vector<TestHeaderCondition>> response_headers;
std::optional<std::vector<TestHeaderCondition>> excluded_response_headers;
base::Value::Dict ToValue() const override;
};
struct TestRuleQueryKeyValue : public DictionarySource {
TestRuleQueryKeyValue();
~TestRuleQueryKeyValue() override;
TestRuleQueryKeyValue(const TestRuleQueryKeyValue&);
TestRuleQueryKeyValue& operator=(const TestRuleQueryKeyValue&);
std::optional<std::string> key;
std::optional<std::string> value;
std::optional<bool> replace_only;
base::Value::Dict ToValue() const override;
};
struct TestRuleQueryTransform : public DictionarySource {
TestRuleQueryTransform();
~TestRuleQueryTransform() override;
TestRuleQueryTransform(const TestRuleQueryTransform&);
TestRuleQueryTransform& operator=(const TestRuleQueryTransform&);
std::optional<std::vector<std::string>> remove_params;
std::optional<std::vector<TestRuleQueryKeyValue>> add_or_replace_params;
base::Value::Dict ToValue() const override;
};
struct TestRuleTransform : public DictionarySource {
TestRuleTransform();
~TestRuleTransform() override;
TestRuleTransform(const TestRuleTransform&);
TestRuleTransform& operator=(const TestRuleTransform&);
std::optional<std::string> scheme;
std::optional<std::string> host;
std::optional<std::string> port;
std::optional<std::string> path;
std::optional<std::string> query;
std::optional<TestRuleQueryTransform> query_transform;
std::optional<std::string> fragment;
std::optional<std::string> username;
std::optional<std::string> password;
base::Value::Dict ToValue() const override;
};
struct TestRuleRedirect : public DictionarySource {
TestRuleRedirect();
~TestRuleRedirect() override;
TestRuleRedirect(const TestRuleRedirect&);
TestRuleRedirect& operator=(const TestRuleRedirect&);
std::optional<std::string> extension_path;
std::optional<TestRuleTransform> transform;
std::optional<std::string> url;
std::optional<std::string> regex_substitution;
base::Value::Dict ToValue() const override;
};
struct TestHeaderInfo : public DictionarySource {
TestHeaderInfo(std::string header,
std::string operation,
std::optional<std::string> value);
~TestHeaderInfo() override;
TestHeaderInfo(const TestHeaderInfo&);
TestHeaderInfo& operator=(const TestHeaderInfo&);
std::optional<std::string> header;
std::optional<std::string> operation;
std::optional<std::string> value;
base::Value::Dict ToValue() const override;
};
struct TestRuleAction : public DictionarySource {
TestRuleAction();
~TestRuleAction() override;
TestRuleAction(const TestRuleAction&);
TestRuleAction& operator=(const TestRuleAction&);
std::optional<std::string> type;
std::optional<std::vector<TestHeaderInfo>> request_headers;
std::optional<std::vector<TestHeaderInfo>> response_headers;
std::optional<TestRuleRedirect> redirect;
base::Value::Dict ToValue() const override;
};
struct TestRule : public DictionarySource {
TestRule();
~TestRule() override;
TestRule(const TestRule&);
TestRule& operator=(const TestRule&);
std::optional<int> id;
std::optional<int> priority;
std::optional<TestRuleCondition> condition;
std::optional<TestRuleAction> action;
base::Value::Dict ToValue() const override;
};
// Helper function to build a generic TestRule.
TestRule CreateGenericRule(int id = kMinValidID);
// Helper function to build a generic regex TestRule.
TestRule CreateRegexRule(int id = kMinValidID);
// Bitmasks to configure the extension under test.
enum ConfigFlag {
kConfig_None = 0,
// Whether a background script ("background.js") will be persisted for the
// extension. Clients can listen in to the "ready" message from the background
// page to detect its loading.
kConfig_HasBackgroundScript = 1 << 0,
// Whether the extension has the declarativeNetRequestFeedback permission.
kConfig_HasFeedbackPermission = 1 << 1,
// Whether the extension has the activeTab permission.
kConfig_HasActiveTab = 1 << 2,
// Whether the "declarative_net_request" manifest key should be omitted.
kConfig_OmitDeclarativeNetRequestKey = 1 << 3,
// Whether the "declarativeNetRequest" permission should be omitted.
kConfig_OmitDeclarativeNetRequestPermission = 1 << 4,
// Whether the "declarativeNetRequestWithHostAccess" permission should be
// included.
kConfig_HasDelarativeNetRequestWithHostAccessPermission = 1 << 5,
// Whether the extension listens for the onUpdateAvailable event. This is
// needed for an extension with a background script to receive delayed
// updates.
kConfig_ListenForOnUpdateAvailable = 1 << 6,
// Whether the extension has an manifest sandbox page entry.
kConfig_HasManifestSandbox = 1 << 7,
// Whether the extension has a manifest action (popup) entry. This is needed
// to activate chrome.action API.
kConfig_HasAction = 1 << 8,
// Whether the "webRequest" permission should be included.
kConfig_HasWebRequestPermission = 1 << 9,
// Whether the "webRequestBlocking" permission should be included. Requires
// MV2 flag below.
kConfig_DEPRECATED_HasWebRequestBlockingPermission = 1 << 10,
// Whether to use deprecated Manifest Version 2.
kConfig_DEPRECATED_ManifestVersion2 = 1 << 11,
};
// Describes a single extension ruleset.
struct TestRulesetInfo {
TestRulesetInfo(const std::string& manifest_id_and_path,
base::Value::List rules_value,
bool enabled = true);
TestRulesetInfo(const std::string& manifest_id,
const std::string& relative_file_path,
base::Value::List rules_value,
bool enabled = true);
// Used to support the copy ctor, or to deliberately create `rules_value` of
// the wrong type.
TestRulesetInfo(const std::string& manifest_id,
const std::string& relative_file_path,
const base::Value& rules_value,
bool enabled = true);
TestRulesetInfo(const TestRulesetInfo&);
TestRulesetInfo& operator=(const TestRulesetInfo&);
// Unique ID for the ruleset.
const std::string manifest_id;
// File path relative to the extension directory.
const std::string relative_file_path;
// The base::Value corresponding to the rules in the ruleset.
const base::Value rules_value;
// Whether the ruleset is enabled by default.
const bool enabled;
// Returns the corresponding value to be specified in the manifest for the
// ruleset.
base::Value::Dict GetManifestValue() const;
};
// Helper to build an extension manifest which uses the
// kDeclarativeNetRequestKey manifest key. `hosts` specifies the host
// permissions to grant. `flags` is a bitmask of ConfigFlag to configure the
// extension. `ruleset_info` specifies the static rulesets for the extension.
base::Value::Dict CreateManifest(
const std::vector<TestRulesetInfo>& ruleset_info,
const std::vector<std::string>& hosts = {},
unsigned flags = ConfigFlag::kConfig_None,
const std::string& extension_name = "Test Extension");
// Returns a base::Value::List corresponding to a vector of strings.
base::Value::List ToListValue(const std::vector<std::string>& vec);
// Returns a base::Value::List corresponding to a vector of TestRules.
base::Value::List ToListValue(const std::vector<TestRule>& rules);
// Writes the rulesets specified in `ruleset_info` in the given `extension_dir`
// together with the manifest file. `hosts` specifies the host permissions, the
// extensions should have. `flags` is a bitmask of ConfigFlag to configure the
// extension.
void WriteManifestAndRulesets(
const base::FilePath& extension_dir,
const std::vector<TestRulesetInfo>& ruleset_info,
const std::vector<std::string>& hosts,
unsigned flags = ConfigFlag::kConfig_None,
const std::string& extension_name = "Test Extension");
// Specialization of WriteManifestAndRulesets above for an extension with a
// single static ruleset.
void WriteManifestAndRuleset(
const base::FilePath& extension_dir,
const TestRulesetInfo& ruleset_info,
const std::vector<std::string>& hosts,
unsigned flags = ConfigFlag::kConfig_None,
const std::string& extension_name = "Test Extension");
} // namespace extensions::declarative_net_request
#endif // EXTENSIONS_COMMON_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_