1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef EXTENSIONS_COMMON_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_
6 #define EXTENSIONS_COMMON_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/files/file_path.h"
13 #include "base/optional.h"
14 #include "base/values.h"
15 #include "extensions/common/api/declarative_net_request/constants.h"
16 #include "extensions/common/url_pattern.h"
17 
18 namespace base {
19 class DictionaryValue;
20 }  // namespace base
21 
22 namespace extensions {
23 namespace declarative_net_request {
24 
25 struct DictionarySource {
26   DictionarySource() = default;
27   virtual ~DictionarySource() = default;
28   virtual std::unique_ptr<base::DictionaryValue> ToValue() const = 0;
29 };
30 
31 // Helper structs to simplify building base::Values which can later be used to
32 // serialize to JSON. The generated implementation for the JSON rules schema is
33 // not used since it's not flexible enough to generate the base::Value/JSON we
34 // want for tests.
35 struct TestRuleCondition : public DictionarySource {
36   TestRuleCondition();
37   ~TestRuleCondition() override;
38   TestRuleCondition(const TestRuleCondition&);
39   TestRuleCondition& operator=(const TestRuleCondition&);
40 
41   base::Optional<std::string> url_filter;
42   base::Optional<std::string> regex_filter;
43   base::Optional<bool> is_url_filter_case_sensitive;
44   base::Optional<std::vector<std::string>> domains;
45   base::Optional<std::vector<std::string>> excluded_domains;
46   base::Optional<std::vector<std::string>> resource_types;
47   base::Optional<std::vector<std::string>> excluded_resource_types;
48   base::Optional<std::string> domain_type;
49 
50   std::unique_ptr<base::DictionaryValue> ToValue() const override;
51 };
52 
53 struct TestRuleQueryKeyValue : public DictionarySource {
54   TestRuleQueryKeyValue();
55   ~TestRuleQueryKeyValue() override;
56   TestRuleQueryKeyValue(const TestRuleQueryKeyValue&);
57   TestRuleQueryKeyValue& operator=(const TestRuleQueryKeyValue&);
58 
59   base::Optional<std::string> key;
60   base::Optional<std::string> value;
61 
62   std::unique_ptr<base::DictionaryValue> ToValue() const override;
63 };
64 
65 struct TestRuleQueryTransform : public DictionarySource {
66   TestRuleQueryTransform();
67   ~TestRuleQueryTransform() override;
68   TestRuleQueryTransform(const TestRuleQueryTransform&);
69   TestRuleQueryTransform& operator=(const TestRuleQueryTransform&);
70 
71   base::Optional<std::vector<std::string>> remove_params;
72   base::Optional<std::vector<TestRuleQueryKeyValue>> add_or_replace_params;
73 
74   std::unique_ptr<base::DictionaryValue> ToValue() const override;
75 };
76 
77 struct TestRuleTransform : public DictionarySource {
78   TestRuleTransform();
79   ~TestRuleTransform() override;
80   TestRuleTransform(const TestRuleTransform&);
81   TestRuleTransform& operator=(const TestRuleTransform&);
82 
83   base::Optional<std::string> scheme;
84   base::Optional<std::string> host;
85   base::Optional<std::string> port;
86   base::Optional<std::string> path;
87   base::Optional<std::string> query;
88   base::Optional<TestRuleQueryTransform> query_transform;
89   base::Optional<std::string> fragment;
90   base::Optional<std::string> username;
91   base::Optional<std::string> password;
92 
93   std::unique_ptr<base::DictionaryValue> ToValue() const override;
94 };
95 
96 struct TestRuleRedirect : public DictionarySource {
97   TestRuleRedirect();
98   ~TestRuleRedirect() override;
99   TestRuleRedirect(const TestRuleRedirect&);
100   TestRuleRedirect& operator=(const TestRuleRedirect&);
101 
102   base::Optional<std::string> extension_path;
103   base::Optional<TestRuleTransform> transform;
104   base::Optional<std::string> url;
105   base::Optional<std::string> regex_substitution;
106 
107   std::unique_ptr<base::DictionaryValue> ToValue() const override;
108 };
109 
110 struct TestHeaderInfo : public DictionarySource {
111   TestHeaderInfo(std::string header,
112                  std::string operation,
113                  base::Optional<std::string> value);
114   ~TestHeaderInfo() override;
115   TestHeaderInfo(const TestHeaderInfo&);
116   TestHeaderInfo& operator=(const TestHeaderInfo&);
117 
118   base::Optional<std::string> header;
119   base::Optional<std::string> operation;
120   base::Optional<std::string> value;
121 
122   std::unique_ptr<base::DictionaryValue> ToValue() const override;
123 };
124 
125 struct TestRuleAction : public DictionarySource {
126   TestRuleAction();
127   ~TestRuleAction() override;
128   TestRuleAction(const TestRuleAction&);
129   TestRuleAction& operator=(const TestRuleAction&);
130 
131   base::Optional<std::string> type;
132   base::Optional<std::vector<TestHeaderInfo>> request_headers;
133   base::Optional<std::vector<TestHeaderInfo>> response_headers;
134   base::Optional<TestRuleRedirect> redirect;
135 
136   std::unique_ptr<base::DictionaryValue> ToValue() const override;
137 };
138 
139 struct TestRule : public DictionarySource {
140   TestRule();
141   ~TestRule() override;
142   TestRule(const TestRule&);
143   TestRule& operator=(const TestRule&);
144 
145   base::Optional<int> id;
146   base::Optional<int> priority;
147   base::Optional<TestRuleCondition> condition;
148   base::Optional<TestRuleAction> action;
149 
150   std::unique_ptr<base::DictionaryValue> ToValue() const override;
151 };
152 
153 // Helper function to build a generic TestRule.
154 TestRule CreateGenericRule(int id = kMinValidID);
155 
156 // Bitmasks to configure the extension under test.
157 enum ConfigFlag {
158   kConfig_None = 0,
159 
160   // Whether a background script ("background.js") will be persisted for the
161   // extension. Clients can listen in to the "ready" message from the background
162   // page to detect its loading.
163   kConfig_HasBackgroundScript = 1 << 0,
164 
165   // Whether the extension has the declarativeNetRequestFeedback permission.
166   kConfig_HasFeedbackPermission = 1 << 1,
167 
168   // Whether the extension has the activeTab permission.
169   kConfig_HasActiveTab = 1 << 2,
170 
171   // Whether the "declarative_net_request" manifest key should be omitted.
172   kConfig_OmitDeclarativeNetRequestKey = 1 << 3,
173 };
174 
175 // Describes a single extension ruleset.
176 struct TestRulesetInfo {
177   TestRulesetInfo(const std::string& manifest_id_and_path,
178                   const base::Value& rules_value,
179                   bool enabled = true);
180   TestRulesetInfo(const std::string& manifest_id,
181                   const std::string& relative_file_path,
182                   const base::Value& rules_value,
183                   bool enabled = true);
184   TestRulesetInfo(const TestRulesetInfo&);
185   TestRulesetInfo& operator=(const TestRulesetInfo&);
186 
187   // Unique ID for the ruleset.
188   const std::string manifest_id;
189 
190   // File path relative to the extension directory.
191   const std::string relative_file_path;
192 
193   // The base::Value corresponding to the rules in the ruleset.
194   const base::Value rules_value;
195 
196   // Whether the ruleset is enabled by default.
197   const bool enabled;
198 
199   // Returns the corresponding value to be specified in the manifest for the
200   // ruleset.
201   std::unique_ptr<base::DictionaryValue> GetManifestValue() const;
202 };
203 
204 // Helper to build an extension manifest which uses the
205 // kDeclarativeNetRequestKey manifest key. |hosts| specifies the host
206 // permissions to grant. |flags| is a bitmask of ConfigFlag to configure the
207 // extension. |ruleset_info| specifies the static rulesets for the extension.
208 std::unique_ptr<base::DictionaryValue> CreateManifest(
209     const std::vector<TestRulesetInfo>& ruleset_info,
210     const std::vector<std::string>& hosts = {},
211     unsigned flags = ConfigFlag::kConfig_None,
212     const std::string& extension_name = "Test Extension");
213 
214 // Returns a ListValue corresponding to a vector of strings.
215 std::unique_ptr<base::ListValue> ToListValue(
216     const std::vector<std::string>& vec);
217 
218 // Returns a ListValue corresponding to a vector of TestRules.
219 std::unique_ptr<base::ListValue> ToListValue(
220     const std::vector<TestRule>& rules);
221 
222 // Writes the rulesets specified in |ruleset_info| in the given |extension_dir|
223 // together with the manifest file. |hosts| specifies the host permissions, the
224 // extensions should have. |flags| is a bitmask of ConfigFlag to configure the
225 // extension.
226 void WriteManifestAndRulesets(
227     const base::FilePath& extension_dir,
228     const std::vector<TestRulesetInfo>& ruleset_info,
229     const std::vector<std::string>& hosts,
230     unsigned flags = ConfigFlag::kConfig_None,
231     const std::string& extension_name = "Test Extension");
232 
233 // Specialization of WriteManifestAndRulesets above for an extension with a
234 // single static ruleset.
235 void WriteManifestAndRuleset(
236     const base::FilePath& extension_dir,
237     const TestRulesetInfo& ruleset_info,
238     const std::vector<std::string>& hosts,
239     unsigned flags = ConfigFlag::kConfig_None,
240     const std::string& extension_name = "Test Extension");
241 
242 }  // namespace declarative_net_request
243 }  // namespace extensions
244 
245 #endif  // EXTENSIONS_COMMON_API_DECLARATIVE_NET_REQUEST_TEST_UTILS_H_
246