1 // Copyright (c) 2012 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_BROWSER_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_ACTION_H_
6 #define EXTENSIONS_BROWSER_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_ACTION_H_
7 
8 #include <list>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 
13 #include "base/compiler_specific.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/optional.h"
17 #include "extensions/browser/api/declarative/declarative_rule.h"
18 #include "extensions/browser/api/declarative_webrequest/request_stage.h"
19 #include "extensions/browser/api/web_request/web_request_api_helpers.h"
20 #include "extensions/common/api/events.h"
21 #include "url/gurl.h"
22 
23 namespace base {
24 class Time;
25 class Value;
26 }
27 
28 namespace extension_web_request_api_helpers {
29 struct EventResponseDelta;
30 }
31 
32 namespace extensions {
33 class Extension;
34 class PermissionHelper;
35 struct WebRequestData;
36 }
37 
38 namespace re2 {
39 class RE2;
40 }
41 
42 namespace extensions {
43 
44 // Base class for all WebRequestActions of the declarative Web Request API.
45 class WebRequestAction : public base::RefCounted<WebRequestAction> {
46  public:
47   // Type identifiers for concrete WebRequestActions. If you add a new type,
48   // also update the unittest WebRequestActionTest.GetName, and add a
49   // WebRequestActionWithThreadsTest.Permission* unittest.
50   enum Type {
51     ACTION_CANCEL_REQUEST,
52     ACTION_REDIRECT_REQUEST,
53     ACTION_REDIRECT_TO_TRANSPARENT_IMAGE,
54     ACTION_REDIRECT_TO_EMPTY_DOCUMENT,
55     ACTION_REDIRECT_BY_REGEX_DOCUMENT,
56     ACTION_SET_REQUEST_HEADER,
57     ACTION_REMOVE_REQUEST_HEADER,
58     ACTION_ADD_RESPONSE_HEADER,
59     ACTION_REMOVE_RESPONSE_HEADER,
60     ACTION_IGNORE_RULES,
61     ACTION_MODIFY_REQUEST_COOKIE,
62     ACTION_MODIFY_RESPONSE_COOKIE,
63     ACTION_SEND_MESSAGE_TO_EXTENSION,
64   };
65 
66   // Strategies for checking host permissions.
67   enum HostPermissionsStrategy {
68     STRATEGY_NONE,     // Do not check host permissions.
69     STRATEGY_DEFAULT,  // Check for host permissions for all URLs
70                        // before creating the delta.
71     STRATEGY_HOST,     // Check that host permissions match the URL
72                        // of the request.
73   };
74 
75   // Information necessary to decide how to apply a WebRequestAction inside a
76   // matching rule. This is passed into HasPermission() and Apply() below as
77   // essentially a parameter pack, so the pointers refer to local structures of
78   // whatever function is calling one of those methods.
79   struct ApplyInfo {
80     PermissionHelper* permission_helper;
81     const WebRequestData& request_data;
82     bool crosses_incognito;
83     // Modified by each applied action:
84     std::list<extension_web_request_api_helpers::EventResponseDelta>* deltas;
85     std::set<std::string>* ignored_tags;
86   };
87 
stages()88   int stages() const {
89     return stages_;
90   }
91 
type()92   Type type() const {
93     return type_;
94   }
95 
96   // Compares the Type of two WebRequestActions, needs to be overridden for
97   // parameterized types.
98   virtual bool Equals(const WebRequestAction* other) const;
99 
100   // Return the JavaScript type name corresponding to type(). If there are
101   // more names, they are returned separated by a colon.
102   virtual std::string GetName() const = 0;
103 
minimum_priority()104   int minimum_priority() const {
105     return minimum_priority_;
106   }
107 
host_permissions_strategy()108   HostPermissionsStrategy host_permissions_strategy() const {
109     return host_permissions_strategy_;
110   }
111 
112   // Returns whether the specified extension has permission to execute this
113   // action on |request|. Checks the host permission if the host permissions
114   // strategy is STRATEGY_DEFAULT.
115   // |apply_info->permission_helper| may only be nullptr for during testing, in
116   // which case host permissions are ignored. |crosses_incognito| specifies
117   // whether the request comes from a different profile than |extension_id|
118   // but was processed because the extension is in spanning mode.
119   bool HasPermission(ApplyInfo* apply_info,
120                      const std::string& extension_id) const;
121 
122   // Factory method that instantiates a concrete WebRequestAction
123   // implementation according to |json_action|, the representation of the
124   // WebRequestAction as received from the extension API.
125   // Sets |error| and returns NULL in case of a semantic error that cannot
126   // be caught by schema validation. Sets |bad_message| and returns NULL
127   // in case the input is syntactically unexpected.
128   static scoped_refptr<const WebRequestAction> Create(
129       content::BrowserContext* browser_context,
130       const Extension* extension,
131       const base::Value& json_action,
132       std::string* error,
133       bool* bad_message);
134 
135   // Returns a description of the modification to the request caused by
136   // this action.
137   virtual base::Optional<extension_web_request_api_helpers::EventResponseDelta>
138   CreateDelta(const WebRequestData& request_data,
139               const std::string& extension_id,
140               const base::Time& extension_install_time) const = 0;
141 
142   // Applies this action to a request, recording the results into
143   // apply_info.deltas.
144   void Apply(const std::string& extension_id,
145              base::Time extension_install_time,
146              ApplyInfo* apply_info) const;
147 
148  protected:
149   friend class base::RefCounted<WebRequestAction>;
150   virtual ~WebRequestAction();
151   WebRequestAction(int stages,
152                    Type type,
153                    int minimum_priority,
154                    HostPermissionsStrategy strategy);
155 
156  private:
157   // A bit vector representing a set of extensions::RequestStage during which
158   // the condition can be tested.
159   const int stages_;
160 
161   const Type type_;
162 
163   // The minimum priority of rules that may be evaluated after the rule
164   // containing this action.
165   const int minimum_priority_;
166 
167   // Defaults to STRATEGY_DEFAULT.
168   const HostPermissionsStrategy host_permissions_strategy_;
169 };
170 
171 typedef DeclarativeActionSet<WebRequestAction> WebRequestActionSet;
172 
173 //
174 // The following are concrete actions.
175 //
176 
177 // Action that instructs to cancel a network request.
178 class WebRequestCancelAction : public WebRequestAction {
179  public:
180   WebRequestCancelAction();
181 
182   // Implementation of WebRequestAction:
183   std::string GetName() const override;
184   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
185   CreateDelta(const WebRequestData& request_data,
186               const std::string& extension_id,
187               const base::Time& extension_install_time) const override;
188 
189  private:
190   ~WebRequestCancelAction() override;
191   DISALLOW_COPY_AND_ASSIGN(WebRequestCancelAction);
192 };
193 
194 // Action that instructs to redirect a network request.
195 class WebRequestRedirectAction : public WebRequestAction {
196  public:
197   explicit WebRequestRedirectAction(const GURL& redirect_url);
198 
199   // Implementation of WebRequestAction:
200   bool Equals(const WebRequestAction* other) const override;
201   std::string GetName() const override;
202   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
203   CreateDelta(const WebRequestData& request_data,
204               const std::string& extension_id,
205               const base::Time& extension_install_time) const override;
206 
207  private:
208   ~WebRequestRedirectAction() override;
209 
210   GURL redirect_url_;  // Target to which the request shall be redirected.
211 
212   DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectAction);
213 };
214 
215 // Action that instructs to redirect a network request to a transparent image.
216 class WebRequestRedirectToTransparentImageAction : public WebRequestAction {
217  public:
218   WebRequestRedirectToTransparentImageAction();
219 
220   // Implementation of WebRequestAction:
221   std::string GetName() const override;
222   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
223   CreateDelta(const WebRequestData& request_data,
224               const std::string& extension_id,
225               const base::Time& extension_install_time) const override;
226 
227  private:
228   ~WebRequestRedirectToTransparentImageAction() override;
229   DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectToTransparentImageAction);
230 };
231 
232 
233 // Action that instructs to redirect a network request to an empty document.
234 class WebRequestRedirectToEmptyDocumentAction : public WebRequestAction {
235  public:
236   WebRequestRedirectToEmptyDocumentAction();
237 
238   // Implementation of WebRequestAction:
239   std::string GetName() const override;
240   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
241   CreateDelta(const WebRequestData& request_data,
242               const std::string& extension_id,
243               const base::Time& extension_install_time) const override;
244 
245  private:
246   ~WebRequestRedirectToEmptyDocumentAction() override;
247   DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectToEmptyDocumentAction);
248 };
249 
250 // Action that instructs to redirect a network request.
251 class WebRequestRedirectByRegExAction : public WebRequestAction {
252  public:
253   // The |to_pattern| has to be passed in RE2 syntax with the exception that
254   // capture groups are referenced in Perl style ($1, $2, ...).
255   explicit WebRequestRedirectByRegExAction(
256       std::unique_ptr<re2::RE2> from_pattern,
257       const std::string& to_pattern);
258 
259   // Conversion of capture group styles between Perl style ($1, $2, ...) and
260   // RE2 (\1, \2, ...).
261   static std::string PerlToRe2Style(const std::string& perl);
262 
263   // Implementation of WebRequestAction:
264   bool Equals(const WebRequestAction* other) const override;
265   std::string GetName() const override;
266   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
267   CreateDelta(const WebRequestData& request_data,
268               const std::string& extension_id,
269               const base::Time& extension_install_time) const override;
270 
271  private:
272   ~WebRequestRedirectByRegExAction() override;
273 
274   std::unique_ptr<re2::RE2> from_pattern_;
275   std::string to_pattern_;
276 
277   DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectByRegExAction);
278 };
279 
280 // Action that instructs to set a request header.
281 class WebRequestSetRequestHeaderAction : public WebRequestAction {
282  public:
283   WebRequestSetRequestHeaderAction(const std::string& name,
284                                    const std::string& value);
285 
286   // Implementation of WebRequestAction:
287   bool Equals(const WebRequestAction* other) const override;
288   std::string GetName() const override;
289   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
290   CreateDelta(const WebRequestData& request_data,
291               const std::string& extension_id,
292               const base::Time& extension_install_time) const override;
293 
294  private:
295   ~WebRequestSetRequestHeaderAction() override;
296 
297   std::string name_;
298   std::string value_;
299   DISALLOW_COPY_AND_ASSIGN(WebRequestSetRequestHeaderAction);
300 };
301 
302 // Action that instructs to remove a request header.
303 class WebRequestRemoveRequestHeaderAction : public WebRequestAction {
304  public:
305   explicit WebRequestRemoveRequestHeaderAction(const std::string& name);
306 
307   // Implementation of WebRequestAction:
308   bool Equals(const WebRequestAction* other) const override;
309   std::string GetName() const override;
310   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
311   CreateDelta(const WebRequestData& request_data,
312               const std::string& extension_id,
313               const base::Time& extension_install_time) const override;
314 
315  private:
316   ~WebRequestRemoveRequestHeaderAction() override;
317 
318   std::string name_;
319   DISALLOW_COPY_AND_ASSIGN(WebRequestRemoveRequestHeaderAction);
320 };
321 
322 // Action that instructs to add a response header.
323 class WebRequestAddResponseHeaderAction : public WebRequestAction {
324  public:
325   WebRequestAddResponseHeaderAction(const std::string& name,
326                                     const std::string& value);
327 
328   // Implementation of WebRequestAction:
329   bool Equals(const WebRequestAction* other) const override;
330   std::string GetName() const override;
331   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
332   CreateDelta(const WebRequestData& request_data,
333               const std::string& extension_id,
334               const base::Time& extension_install_time) const override;
335 
336  private:
337   ~WebRequestAddResponseHeaderAction() override;
338 
339   std::string name_;
340   std::string value_;
341   DISALLOW_COPY_AND_ASSIGN(WebRequestAddResponseHeaderAction);
342 };
343 
344 // Action that instructs to remove a response header.
345 class WebRequestRemoveResponseHeaderAction : public WebRequestAction {
346  public:
347   explicit WebRequestRemoveResponseHeaderAction(const std::string& name,
348                                                 const std::string& value,
349                                                 bool has_value);
350 
351   // Implementation of WebRequestAction:
352   bool Equals(const WebRequestAction* other) const override;
353   std::string GetName() const override;
354   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
355   CreateDelta(const WebRequestData& request_data,
356               const std::string& extension_id,
357               const base::Time& extension_install_time) const override;
358 
359  private:
360   ~WebRequestRemoveResponseHeaderAction() override;
361 
362   std::string name_;
363   std::string value_;
364   bool has_value_;
365   DISALLOW_COPY_AND_ASSIGN(WebRequestRemoveResponseHeaderAction);
366 };
367 
368 // Action that instructs to ignore rules below a certain priority.
369 class WebRequestIgnoreRulesAction : public WebRequestAction {
370  public:
371   explicit WebRequestIgnoreRulesAction(int minimum_priority,
372                                        const std::string& ignore_tag);
373 
374   // Implementation of WebRequestAction:
375   bool Equals(const WebRequestAction* other) const override;
376   std::string GetName() const override;
377   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
378   CreateDelta(const WebRequestData& request_data,
379               const std::string& extension_id,
380               const base::Time& extension_install_time) const override;
ignore_tag()381   const std::string& ignore_tag() const { return ignore_tag_; }
382 
383  private:
384   ~WebRequestIgnoreRulesAction() override;
385 
386   // Rules are ignored if they have a tag matching |ignore_tag_| and
387   // |ignore_tag_| is non-empty.
388   std::string ignore_tag_;
389   DISALLOW_COPY_AND_ASSIGN(WebRequestIgnoreRulesAction);
390 };
391 
392 // Action that instructs to modify (add, edit, remove) a request cookie.
393 class WebRequestRequestCookieAction : public WebRequestAction {
394  public:
395   typedef extension_web_request_api_helpers::RequestCookieModification
396       RequestCookieModification;
397 
398   explicit WebRequestRequestCookieAction(
399       RequestCookieModification request_cookie_modification);
400 
401   // Implementation of WebRequestAction:
402   bool Equals(const WebRequestAction* other) const override;
403   std::string GetName() const override;
404   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
405   CreateDelta(const WebRequestData& request_data,
406               const std::string& extension_id,
407               const base::Time& extension_install_time) const override;
408 
409  private:
410   ~WebRequestRequestCookieAction() override;
411 
412   const RequestCookieModification request_cookie_modification_;
413   DISALLOW_COPY_AND_ASSIGN(WebRequestRequestCookieAction);
414 };
415 
416 // Action that instructs to modify (add, edit, remove) a response cookie.
417 class WebRequestResponseCookieAction : public WebRequestAction {
418  public:
419   typedef extension_web_request_api_helpers::ResponseCookieModification
420       ResponseCookieModification;
421 
422   explicit WebRequestResponseCookieAction(
423       ResponseCookieModification response_cookie_modification);
424 
425   // Implementation of WebRequestAction:
426   bool Equals(const WebRequestAction* other) const override;
427   std::string GetName() const override;
428   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
429   CreateDelta(const WebRequestData& request_data,
430               const std::string& extension_id,
431               const base::Time& extension_install_time) const override;
432 
433  private:
434   ~WebRequestResponseCookieAction() override;
435 
436   const ResponseCookieModification response_cookie_modification_;
437   DISALLOW_COPY_AND_ASSIGN(WebRequestResponseCookieAction);
438 };
439 
440 // Action that triggers the chrome.declarativeWebRequest.onMessage event in
441 // the background/event/... pages of the extension.
442 class WebRequestSendMessageToExtensionAction : public WebRequestAction {
443  public:
444   explicit WebRequestSendMessageToExtensionAction(const std::string& message);
445 
446   // Implementation of WebRequestAction:
447   bool Equals(const WebRequestAction* other) const override;
448   std::string GetName() const override;
449   base::Optional<extension_web_request_api_helpers::EventResponseDelta>
450   CreateDelta(const WebRequestData& request_data,
451               const std::string& extension_id,
452               const base::Time& extension_install_time) const override;
453 
454  private:
455   ~WebRequestSendMessageToExtensionAction() override;
456 
457   std::string message_;
458   DISALLOW_COPY_AND_ASSIGN(WebRequestSendMessageToExtensionAction);
459 };
460 
461 }  // namespace extensions
462 
463 #endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_ACTION_H_
464