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 <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 "extensions/browser/api/declarative/declarative_rule.h"
16#include "extensions/browser/api/declarative_webrequest/request_stage.h"
17#include "extensions/browser/api/web_request/web_request_api_helpers.h"
18#include "extensions/common/api/events.h"
19#include "url/gurl.h"
20
21class WebRequestPermission;
22
23namespace base {
24class DictionaryValue;
25class Time;
26class Value;
27}
28
29namespace extension_web_request_api_helpers {
30struct EventResponseDelta;
31}
32
33namespace extensions {
34class Extension;
35class InfoMap;
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 InfoMap* 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 InfoMap* 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      content::BrowserContext* browser_context,
138      const Extension* extension,
139      const base::Value& json_action,
140      std::string* error,
141      bool* bad_message);
142
143  // Returns a description of the modification to the request caused by
144  // this action.
145  virtual LinkedPtrEventResponseDelta CreateDelta(
146      const WebRequestData& request_data,
147      const std::string& extension_id,
148      const base::Time& extension_install_time) const = 0;
149
150  // Applies this action to a request, recording the results into
151  // apply_info.deltas.
152  void Apply(const std::string& extension_id,
153             base::Time extension_install_time,
154             ApplyInfo* apply_info) const;
155
156 protected:
157  friend class base::RefCounted<WebRequestAction>;
158  virtual ~WebRequestAction();
159  WebRequestAction(int stages,
160                   Type type,
161                   int minimum_priority,
162                   HostPermissionsStrategy strategy);
163
164 private:
165  // A bit vector representing a set of extensions::RequestStage during which
166  // the condition can be tested.
167  const int stages_;
168
169  const Type type_;
170
171  // The minimum priority of rules that may be evaluated after the rule
172  // containing this action.
173  const int minimum_priority_;
174
175  // Defaults to STRATEGY_DEFAULT.
176  const HostPermissionsStrategy host_permissions_strategy_;
177};
178
179typedef DeclarativeActionSet<WebRequestAction> WebRequestActionSet;
180
181//
182// The following are concrete actions.
183//
184
185// Action that instructs to cancel a network request.
186class WebRequestCancelAction : public WebRequestAction {
187 public:
188  WebRequestCancelAction();
189
190  // Implementation of WebRequestAction:
191  virtual std::string GetName() const OVERRIDE;
192  virtual LinkedPtrEventResponseDelta CreateDelta(
193      const WebRequestData& request_data,
194      const std::string& extension_id,
195      const base::Time& extension_install_time) const OVERRIDE;
196
197 private:
198  virtual ~WebRequestCancelAction();
199  DISALLOW_COPY_AND_ASSIGN(WebRequestCancelAction);
200};
201
202// Action that instructs to redirect a network request.
203class WebRequestRedirectAction : public WebRequestAction {
204 public:
205  explicit WebRequestRedirectAction(const GURL& redirect_url);
206
207  // Implementation of WebRequestAction:
208  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
209  virtual std::string GetName() const OVERRIDE;
210  virtual LinkedPtrEventResponseDelta CreateDelta(
211      const WebRequestData& request_data,
212      const std::string& extension_id,
213      const base::Time& extension_install_time) const OVERRIDE;
214
215 private:
216  virtual ~WebRequestRedirectAction();
217
218  GURL redirect_url_;  // Target to which the request shall be redirected.
219
220  DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectAction);
221};
222
223// Action that instructs to redirect a network request to a transparent image.
224class WebRequestRedirectToTransparentImageAction : public WebRequestAction {
225 public:
226  WebRequestRedirectToTransparentImageAction();
227
228  // Implementation of WebRequestAction:
229  virtual std::string GetName() const OVERRIDE;
230  virtual LinkedPtrEventResponseDelta CreateDelta(
231      const WebRequestData& request_data,
232      const std::string& extension_id,
233      const base::Time& extension_install_time) const OVERRIDE;
234
235 private:
236  virtual ~WebRequestRedirectToTransparentImageAction();
237  DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectToTransparentImageAction);
238};
239
240
241// Action that instructs to redirect a network request to an empty document.
242class WebRequestRedirectToEmptyDocumentAction : public WebRequestAction {
243 public:
244  WebRequestRedirectToEmptyDocumentAction();
245
246  // Implementation of WebRequestAction:
247  virtual std::string GetName() const OVERRIDE;
248  virtual LinkedPtrEventResponseDelta CreateDelta(
249      const WebRequestData& request_data,
250      const std::string& extension_id,
251      const base::Time& extension_install_time) const OVERRIDE;
252
253 private:
254  virtual ~WebRequestRedirectToEmptyDocumentAction();
255  DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectToEmptyDocumentAction);
256};
257
258// Action that instructs to redirect a network request.
259class WebRequestRedirectByRegExAction : public WebRequestAction {
260 public:
261  // The |to_pattern| has to be passed in RE2 syntax with the exception that
262  // capture groups are referenced in Perl style ($1, $2, ...).
263  explicit WebRequestRedirectByRegExAction(scoped_ptr<re2::RE2> from_pattern,
264                                           const std::string& to_pattern);
265
266  // Conversion of capture group styles between Perl style ($1, $2, ...) and
267  // RE2 (\1, \2, ...).
268  static std::string PerlToRe2Style(const std::string& perl);
269
270  // Implementation of WebRequestAction:
271  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
272  virtual std::string GetName() const OVERRIDE;
273  virtual LinkedPtrEventResponseDelta CreateDelta(
274      const WebRequestData& request_data,
275      const std::string& extension_id,
276      const base::Time& extension_install_time) const OVERRIDE;
277
278 private:
279  virtual ~WebRequestRedirectByRegExAction();
280
281  scoped_ptr<re2::RE2> from_pattern_;
282  std::string to_pattern_;
283
284  DISALLOW_COPY_AND_ASSIGN(WebRequestRedirectByRegExAction);
285};
286
287// Action that instructs to set a request header.
288class WebRequestSetRequestHeaderAction : public WebRequestAction {
289 public:
290  WebRequestSetRequestHeaderAction(const std::string& name,
291                                   const std::string& value);
292
293  // Implementation of WebRequestAction:
294  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
295  virtual std::string GetName() const OVERRIDE;
296  virtual LinkedPtrEventResponseDelta CreateDelta(
297      const WebRequestData& request_data,
298      const std::string& extension_id,
299      const base::Time& extension_install_time) const OVERRIDE;
300
301 private:
302  virtual ~WebRequestSetRequestHeaderAction();
303
304  std::string name_;
305  std::string value_;
306  DISALLOW_COPY_AND_ASSIGN(WebRequestSetRequestHeaderAction);
307};
308
309// Action that instructs to remove a request header.
310class WebRequestRemoveRequestHeaderAction : public WebRequestAction {
311 public:
312  explicit WebRequestRemoveRequestHeaderAction(const std::string& name);
313
314  // Implementation of WebRequestAction:
315  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
316  virtual std::string GetName() const OVERRIDE;
317  virtual LinkedPtrEventResponseDelta CreateDelta(
318      const WebRequestData& request_data,
319      const std::string& extension_id,
320      const base::Time& extension_install_time) const OVERRIDE;
321
322 private:
323  virtual ~WebRequestRemoveRequestHeaderAction();
324
325  std::string name_;
326  DISALLOW_COPY_AND_ASSIGN(WebRequestRemoveRequestHeaderAction);
327};
328
329// Action that instructs to add a response header.
330class WebRequestAddResponseHeaderAction : public WebRequestAction {
331 public:
332  WebRequestAddResponseHeaderAction(const std::string& name,
333                                    const std::string& value);
334
335  // Implementation of WebRequestAction:
336  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
337  virtual std::string GetName() const OVERRIDE;
338  virtual LinkedPtrEventResponseDelta CreateDelta(
339      const WebRequestData& request_data,
340      const std::string& extension_id,
341      const base::Time& extension_install_time) const OVERRIDE;
342
343 private:
344  virtual ~WebRequestAddResponseHeaderAction();
345
346  std::string name_;
347  std::string value_;
348  DISALLOW_COPY_AND_ASSIGN(WebRequestAddResponseHeaderAction);
349};
350
351// Action that instructs to remove a response header.
352class WebRequestRemoveResponseHeaderAction : public WebRequestAction {
353 public:
354  explicit WebRequestRemoveResponseHeaderAction(const std::string& name,
355                                                const std::string& value,
356                                                bool has_value);
357
358  // Implementation of WebRequestAction:
359  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
360  virtual std::string GetName() const OVERRIDE;
361  virtual LinkedPtrEventResponseDelta CreateDelta(
362      const WebRequestData& request_data,
363      const std::string& extension_id,
364      const base::Time& extension_install_time) const OVERRIDE;
365
366 private:
367  virtual ~WebRequestRemoveResponseHeaderAction();
368
369  std::string name_;
370  std::string value_;
371  bool has_value_;
372  DISALLOW_COPY_AND_ASSIGN(WebRequestRemoveResponseHeaderAction);
373};
374
375// Action that instructs to ignore rules below a certain priority.
376class WebRequestIgnoreRulesAction : public WebRequestAction {
377 public:
378  explicit WebRequestIgnoreRulesAction(int minimum_priority,
379                                       const std::string& ignore_tag);
380
381  // Implementation of WebRequestAction:
382  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
383  virtual std::string GetName() const OVERRIDE;
384  virtual LinkedPtrEventResponseDelta CreateDelta(
385      const WebRequestData& request_data,
386      const std::string& extension_id,
387      const base::Time& extension_install_time) const OVERRIDE;
388  const std::string& ignore_tag() const { return ignore_tag_; }
389
390 private:
391  virtual ~WebRequestIgnoreRulesAction();
392
393  // Rules are ignored if they have a tag matching |ignore_tag_| and
394  // |ignore_tag_| is non-empty.
395  std::string ignore_tag_;
396  DISALLOW_COPY_AND_ASSIGN(WebRequestIgnoreRulesAction);
397};
398
399// Action that instructs to modify (add, edit, remove) a request cookie.
400class WebRequestRequestCookieAction : public WebRequestAction {
401 public:
402  typedef extension_web_request_api_helpers::RequestCookieModification
403      RequestCookieModification;
404
405  explicit WebRequestRequestCookieAction(
406      linked_ptr<RequestCookieModification> request_cookie_modification);
407
408  // Implementation of WebRequestAction:
409  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
410  virtual std::string GetName() const OVERRIDE;
411  virtual LinkedPtrEventResponseDelta CreateDelta(
412      const WebRequestData& request_data,
413      const std::string& extension_id,
414      const base::Time& extension_install_time) const OVERRIDE;
415
416 private:
417  virtual ~WebRequestRequestCookieAction();
418
419  linked_ptr<RequestCookieModification> request_cookie_modification_;
420  DISALLOW_COPY_AND_ASSIGN(WebRequestRequestCookieAction);
421};
422
423// Action that instructs to modify (add, edit, remove) a response cookie.
424class WebRequestResponseCookieAction : public WebRequestAction {
425 public:
426  typedef extension_web_request_api_helpers::ResponseCookieModification
427      ResponseCookieModification;
428
429  explicit WebRequestResponseCookieAction(
430      linked_ptr<ResponseCookieModification> response_cookie_modification);
431
432  // Implementation of WebRequestAction:
433  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
434  virtual std::string GetName() const OVERRIDE;
435  virtual LinkedPtrEventResponseDelta CreateDelta(
436      const WebRequestData& request_data,
437      const std::string& extension_id,
438      const base::Time& extension_install_time) const OVERRIDE;
439
440 private:
441  virtual ~WebRequestResponseCookieAction();
442
443  linked_ptr<ResponseCookieModification> response_cookie_modification_;
444  DISALLOW_COPY_AND_ASSIGN(WebRequestResponseCookieAction);
445};
446
447// Action that triggers the chrome.declarativeWebRequest.onMessage event in
448// the background/event/... pages of the extension.
449class WebRequestSendMessageToExtensionAction : public WebRequestAction {
450 public:
451  explicit WebRequestSendMessageToExtensionAction(const std::string& message);
452
453  // Implementation of WebRequestAction:
454  virtual bool Equals(const WebRequestAction* other) const OVERRIDE;
455  virtual std::string GetName() const OVERRIDE;
456  virtual LinkedPtrEventResponseDelta CreateDelta(
457      const WebRequestData& request_data,
458      const std::string& extension_id,
459      const base::Time& extension_install_time) const OVERRIDE;
460
461 private:
462  virtual ~WebRequestSendMessageToExtensionAction();
463
464  std::string message_;
465  DISALLOW_COPY_AND_ASSIGN(WebRequestSendMessageToExtensionAction);
466};
467
468}  // namespace extensions
469
470#endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_ACTION_H_
471