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