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// Helper classes and functions used for the WebRequest API.
6
7#ifndef CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
8#define CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
9
10#include <list>
11#include <set>
12#include <string>
13
14#include "base/memory/linked_ptr.h"
15#include "base/memory/ref_counted.h"
16#include "base/memory/scoped_ptr.h"
17#include "base/time/time.h"
18#include "chrome/browser/extensions/extension_warning_set.h"
19#include "net/base/auth.h"
20#include "net/http/http_request_headers.h"
21#include "net/http/http_response_headers.h"
22#include "url/gurl.h"
23#include "webkit/common/resource_type.h"
24
25namespace base {
26class ListValue;
27class Value;
28}
29
30namespace extensions {
31class Extension;
32}
33
34namespace net {
35class BoundNetLog;
36class URLRequest;
37}
38
39namespace extension_web_request_api_helpers {
40
41typedef std::pair<std::string, std::string> ResponseHeader;
42typedef std::vector<ResponseHeader> ResponseHeaders;
43
44// Data container for RequestCookies as defined in the declarative WebRequest
45// API definition.
46struct RequestCookie {
47  RequestCookie();
48  ~RequestCookie();
49  scoped_ptr<std::string> name;
50  scoped_ptr<std::string> value;
51 private:
52  DISALLOW_COPY_AND_ASSIGN(RequestCookie);
53};
54
55bool NullableEquals(const RequestCookie* a, const RequestCookie* b);
56
57// Data container for ResponseCookies as defined in the declarative WebRequest
58// API definition.
59struct ResponseCookie {
60  ResponseCookie();
61  ~ResponseCookie();
62  scoped_ptr<std::string> name;
63  scoped_ptr<std::string> value;
64  scoped_ptr<std::string> expires;
65  scoped_ptr<int> max_age;
66  scoped_ptr<std::string> domain;
67  scoped_ptr<std::string> path;
68  scoped_ptr<bool> secure;
69  scoped_ptr<bool> http_only;
70 private:
71  DISALLOW_COPY_AND_ASSIGN(ResponseCookie);
72};
73
74bool NullableEquals(const ResponseCookie* a, const ResponseCookie* b);
75
76// Data container for FilterResponseCookies as defined in the declarative
77// WebRequest API definition.
78struct FilterResponseCookie : ResponseCookie {
79  FilterResponseCookie();
80  ~FilterResponseCookie();
81  scoped_ptr<int> age_lower_bound;
82  scoped_ptr<int> age_upper_bound;
83  scoped_ptr<bool> session_cookie;
84 private:
85  DISALLOW_COPY_AND_ASSIGN(FilterResponseCookie);
86};
87
88bool NullableEquals(const FilterResponseCookie* a,
89                    const FilterResponseCookie* b);
90
91enum CookieModificationType {
92  ADD,
93  EDIT,
94  REMOVE,
95};
96
97struct RequestCookieModification {
98  RequestCookieModification();
99  ~RequestCookieModification();
100  CookieModificationType type;
101  // Used for EDIT and REMOVE. NULL for ADD.
102  scoped_ptr<RequestCookie> filter;
103  // Used for ADD and EDIT. NULL for REMOVE.
104  scoped_ptr<RequestCookie> modification;
105 private:
106  DISALLOW_COPY_AND_ASSIGN(RequestCookieModification);
107};
108
109bool NullableEquals(const RequestCookieModification* a,
110                    const RequestCookieModification* b);
111
112struct ResponseCookieModification {
113  ResponseCookieModification();
114  ~ResponseCookieModification();
115  CookieModificationType type;
116  // Used for EDIT and REMOVE.
117  scoped_ptr<FilterResponseCookie> filter;
118  // Used for ADD and EDIT.
119  scoped_ptr<ResponseCookie> modification;
120 private:
121  DISALLOW_COPY_AND_ASSIGN(ResponseCookieModification);
122};
123
124bool NullableEquals(const ResponseCookieModification* a,
125                    const ResponseCookieModification* b);
126
127typedef std::vector<linked_ptr<RequestCookieModification> >
128    RequestCookieModifications;
129typedef std::vector<linked_ptr<ResponseCookieModification> >
130    ResponseCookieModifications;
131
132// Contains the modification an extension wants to perform on an event.
133struct EventResponseDelta {
134  // ID of the extension that sent this response.
135  std::string extension_id;
136
137  // The time that the extension was installed. Used for deciding order of
138  // precedence in case multiple extensions respond with conflicting
139  // decisions.
140  base::Time extension_install_time;
141
142  // Response values. These are mutually exclusive.
143  bool cancel;
144  GURL new_url;
145
146  // Newly introduced or overridden request headers.
147  net::HttpRequestHeaders modified_request_headers;
148
149  // Keys of request headers to be deleted.
150  std::vector<std::string> deleted_request_headers;
151
152  // Headers that were added to the response. A modification of a header
153  // corresponds to a deletion and subsequent addition of the new header.
154  ResponseHeaders added_response_headers;
155
156  // Headers that were deleted from the response.
157  ResponseHeaders deleted_response_headers;
158
159  // Authentication Credentials to use.
160  scoped_ptr<net::AuthCredentials> auth_credentials;
161
162  // Modifications to cookies in request headers.
163  RequestCookieModifications request_cookie_modifications;
164
165  // Modifications to cookies in response headers.
166  ResponseCookieModifications response_cookie_modifications;
167
168  // Messages that shall be sent to the background/event/... pages of the
169  // extension.
170  std::set<std::string> messages_to_extension;
171
172  EventResponseDelta(const std::string& extension_id,
173                     const base::Time& extension_install_time);
174  ~EventResponseDelta();
175
176  DISALLOW_COPY_AND_ASSIGN(EventResponseDelta);
177};
178
179typedef std::list<linked_ptr<EventResponseDelta> > EventResponseDeltas;
180
181// Comparison operator that returns true if the extension that caused
182// |a| was installed after the extension that caused |b|.
183bool InDecreasingExtensionInstallationTimeOrder(
184    const linked_ptr<EventResponseDelta>& a,
185    const linked_ptr<EventResponseDelta>& b);
186
187// Converts a string to a list of integers, each in 0..255. Ownership
188// of the created list is passed to the caller.
189base::ListValue* StringToCharList(const std::string& s);
190
191// Converts a list of integer values between 0 and 255 into a string |*out|.
192// Returns true if the conversion was successful.
193bool CharListToString(const base::ListValue* list, std::string* out);
194
195// The following functions calculate and return the modifications to requests
196// commanded by extension handlers. All functions take the id of the extension
197// that commanded a modification, the installation time of this extension (used
198// for defining a precedence in conflicting modifications) and whether the
199// extension requested to |cancel| the request. Other parameters depend on a
200// the signal handler. Ownership of the returned object is passed to the caller.
201
202EventResponseDelta* CalculateOnBeforeRequestDelta(
203    const std::string& extension_id,
204    const base::Time& extension_install_time,
205    bool cancel,
206    const GURL& new_url);
207EventResponseDelta* CalculateOnBeforeSendHeadersDelta(
208    const std::string& extension_id,
209    const base::Time& extension_install_time,
210    bool cancel,
211    net::HttpRequestHeaders* old_headers,
212    net::HttpRequestHeaders* new_headers);
213EventResponseDelta* CalculateOnHeadersReceivedDelta(
214    const std::string& extension_id,
215    const base::Time& extension_install_time,
216    bool cancel,
217    const net::HttpResponseHeaders* old_response_headers,
218    ResponseHeaders* new_response_headers);
219// Destructively moves the auth credentials from |auth_credentials| to the
220// returned EventResponseDelta.
221EventResponseDelta* CalculateOnAuthRequiredDelta(
222    const std::string& extension_id,
223    const base::Time& extension_install_time,
224    bool cancel,
225    scoped_ptr<net::AuthCredentials>* auth_credentials);
226
227// These functions merge the responses (the |deltas|) of request handlers.
228// The |deltas| need to be sorted in decreasing order of precedence of
229// extensions. In case extensions had |deltas| that could not be honored, their
230// IDs are reported in |conflicting_extensions|. NetLog events that shall be
231// reported will be stored in |event_log_entries|.
232
233// Stores in |canceled| whether any extension wanted to cancel the request.
234void MergeCancelOfResponses(
235    const EventResponseDeltas& deltas,
236    bool* canceled,
237    const net::BoundNetLog* net_log);
238// Stores in |*new_url| the redirect request of the extension with highest
239// precedence. Extensions that did not command to redirect the request are
240// ignored in this logic.
241void MergeOnBeforeRequestResponses(
242    const EventResponseDeltas& deltas,
243    GURL* new_url,
244    extensions::ExtensionWarningSet* conflicting_extensions,
245    const net::BoundNetLog* net_log);
246// Modifies the "Cookie" header in |request_headers| according to
247// |deltas.request_cookie_modifications|. Conflicts are currently ignored
248// silently.
249void MergeCookiesInOnBeforeSendHeadersResponses(
250    const EventResponseDeltas& deltas,
251    net::HttpRequestHeaders* request_headers,
252    extensions::ExtensionWarningSet* conflicting_extensions,
253    const net::BoundNetLog* net_log);
254// Modifies the headers in |request_headers| according to |deltas|. Conflicts
255// are tried to be resolved.
256void MergeOnBeforeSendHeadersResponses(
257    const EventResponseDeltas& deltas,
258    net::HttpRequestHeaders* request_headers,
259    extensions::ExtensionWarningSet* conflicting_extensions,
260    const net::BoundNetLog* net_log);
261// Modifies the "Set-Cookie" headers in |override_response_headers| according to
262// |deltas.response_cookie_modifications|. If |override_response_headers| is
263// NULL, a copy of |original_response_headers| is created. Conflicts are
264// currently ignored silently.
265void MergeCookiesInOnHeadersReceivedResponses(
266    const EventResponseDeltas& deltas,
267    const net::HttpResponseHeaders* original_response_headers,
268    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
269    extensions::ExtensionWarningSet* conflicting_extensions,
270    const net::BoundNetLog* net_log);
271// Stores a copy of |original_response_header| into |override_response_headers|
272// that is modified according to |deltas|. If |deltas| does not instruct to
273// modify the response headers, |override_response_headers| remains empty.
274void MergeOnHeadersReceivedResponses(
275    const EventResponseDeltas& deltas,
276    const net::HttpResponseHeaders* original_response_headers,
277    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
278    extensions::ExtensionWarningSet* conflicting_extensions,
279    const net::BoundNetLog* net_log);
280// Merge the responses of blocked onAuthRequired handlers. The first
281// registered listener that supplies authentication credentials in a response,
282// if any, will have its authentication credentials used. |request| must be
283// non-NULL, and contain |deltas| that are sorted in decreasing order of
284// precedence.
285// Returns whether authentication credentials are set.
286bool MergeOnAuthRequiredResponses(
287    const EventResponseDeltas& deltas,
288    net::AuthCredentials* auth_credentials,
289    extensions::ExtensionWarningSet* conflicting_extensions,
290    const net::BoundNetLog* net_log);
291
292// Returns whether |type| is a ResourceType that is handled by the web request
293// API.
294bool IsRelevantResourceType(ResourceType::Type type);
295
296// Returns a string representation of |type| or |other| if |type| is not handled
297// by the web request API.
298const char* ResourceTypeToString(ResourceType::Type type);
299
300// Stores a |ResourceType::Type| representation in |type| if |type_str| is
301// a resource type handled by the web request API. Returns true in case of
302// success.
303bool ParseResourceType(const std::string& type_str,
304                       ResourceType::Type* type);
305
306// Triggers clearing each renderer's in-memory cache the next time it navigates.
307void ClearCacheOnNavigation();
308
309// Tells renderer processes that the web request or declarative web request
310// API has been used by |extension| in profile |profile_id| to collect
311// UMA statistics on Page Load Times. Needs to be called on the UI thread.
312void NotifyWebRequestAPIUsed(
313    void* profile_id,
314    scoped_refptr<const extensions::Extension> extension);
315
316}  // namespace extension_web_request_api_helpers
317
318#endif  // CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
319