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 EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
8 #define EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
9 
10 #include <list>
11 #include <memory>
12 #include <set>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 #include "base/macros.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/optional.h"
20 #include "base/time/time.h"
21 #include "extensions/common/api/web_request.h"
22 #include "extensions/common/extension_id.h"
23 #include "net/base/auth.h"
24 #include "net/http/http_request_headers.h"
25 #include "net/http/http_response_headers.h"
26 #include "services/network/public/cpp/features.h"
27 #include "url/gurl.h"
28 
29 namespace base {
30 class ListValue;
31 class DictionaryValue;
32 }  // namespace base
33 
34 namespace content {
35 class BrowserContext;
36 }
37 
38 namespace extensions {
39 class Extension;
40 struct WebRequestInfo;
41 
42 namespace declarative_net_request {
43 struct RequestAction;
44 }  // namespace declarative_net_request
45 
46 }  // namespace extensions
47 
48 namespace extension_web_request_api_helpers {
49 
50 using ResponseHeader = std::pair<std::string, std::string>;
51 using ResponseHeaders = std::vector<ResponseHeader>;
52 
53 // These values are persisted to logs. Entries should not be renumbered and
54 // numeric values should never be reused.
55 enum class RequestHeaderType {
56   kNone = 0,
57   kOther = 1,
58   kAccept = 2,
59   kAcceptCharset = 3,
60   kAcceptEncoding = 4,
61   kAcceptLanguage = 5,
62   kAccessControlRequestHeaders = 6,
63   kAccessControlRequestMethod = 7,
64   kAuthorization = 8,
65   kCacheControl = 9,
66   kConnection = 10,
67   kContentEncoding = 11,
68   kContentLanguage = 12,
69   kContentLength = 13,
70   kContentLocation = 14,
71   kContentType = 15,
72   kCookie = 16,
73   kDate = 17,
74   kDnt = 18,
75   kEarlyData = 19,
76   kExpect = 20,
77   kForwarded = 21,
78   kFrom = 22,
79   kHost = 23,
80   kIfMatch = 24,
81   kIfModifiedSince = 25,
82   kIfNoneMatch = 26,
83   kIfRange = 27,
84   kIfUnmodifiedSince = 28,
85   kKeepAlive = 29,
86   kOrigin = 30,
87   kPragma = 31,
88   kProxyAuthorization = 32,
89   kProxyConnection = 33,
90   kRange = 34,
91   kReferer = 35,
92   //  kSecOriginPolicy = 36, // no longer shipping
93   kTe = 37,
94   kTransferEncoding = 38,
95   kUpgrade = 39,
96   kUpgradeInsecureRequests = 40,
97   kUserAgent = 41,
98   kVia = 42,
99   kWarning = 43,
100   kXForwardedFor = 44,
101   kXForwardedHost = 45,
102   kXForwardedProto = 46,
103   kMaxValue = kXForwardedProto,
104 };
105 
106 // These values are persisted to logs. Entries should not be renumbered and
107 // numeric values should never be reused.
108 enum class ResponseHeaderType {
109   kNone = 0,
110   kOther = 1,
111   kAcceptPatch = 2,
112   kAcceptRanges = 3,
113   kAccessControlAllowCredentials = 4,
114   kAccessControlAllowHeaders = 5,
115   kAccessControlAllowMethods = 6,
116   kAccessControlAllowOrigin = 7,
117   kAccessControlExposeHeaders = 8,
118   kAccessControlMaxAge = 9,
119   kAge = 10,
120   kAllow = 11,
121   kAltSvc = 12,
122   kCacheControl = 13,
123   kClearSiteData = 14,
124   kConnection = 15,
125   kContentDisposition = 16,
126   kContentEncoding = 17,
127   kContentLanguage = 18,
128   kContentLength = 19,
129   kContentLocation = 20,
130   kContentRange = 21,
131   kContentSecurityPolicy = 22,
132   kContentSecurityPolicyReportOnly = 23,
133   kContentType = 24,
134   kDate = 25,
135   kETag = 26,
136   kExpectCT = 27,
137   kExpires = 28,
138   kFeaturePolicy = 29,
139   kKeepAlive = 30,
140   kLargeAllocation = 31,
141   kLastModified = 32,
142   kLocation = 33,
143   kPragma = 34,
144   kProxyAuthenticate = 35,
145   kProxyConnection = 36,
146   kPublicKeyPins = 37,
147   kPublicKeyPinsReportOnly = 38,
148   kReferrerPolicy = 39,
149   kRefresh = 40,
150   kRetryAfter = 41,
151   kSecWebSocketAccept = 42,
152   kServer = 43,
153   kServerTiming = 44,
154   kSetCookie = 45,
155   kSourceMap = 46,
156   kStrictTransportSecurity = 47,
157   kTimingAllowOrigin = 48,
158   kTk = 49,
159   kTrailer = 50,
160   kTransferEncoding = 51,
161   kUpgrade = 52,
162   kVary = 53,
163   kVia = 54,
164   kWarning = 55,
165   kWWWAuthenticate = 56,
166   kXContentTypeOptions = 57,
167   kXDNSPrefetchControl = 58,
168   kXFrameOptions = 59,
169   kXXSSProtection = 60,
170   kMaxValue = kXXSSProtection
171 };
172 
173 struct IgnoredAction {
174   IgnoredAction(extensions::ExtensionId extension_id,
175                 extensions::api::web_request::IgnoredActionType action_type);
176   IgnoredAction(IgnoredAction&& rhs);
177 
178   extensions::ExtensionId extension_id;
179   extensions::api::web_request::IgnoredActionType action_type;
180 
181  private:
182   DISALLOW_COPY_AND_ASSIGN(IgnoredAction);
183 };
184 
185 using IgnoredActions = std::vector<IgnoredAction>;
186 
187 // Internal representation of the extraInfoSpec parameter on webRequest
188 // events, used to specify extra information to be included with network
189 // events.
190 struct ExtraInfoSpec {
191   enum Flags {
192     REQUEST_HEADERS = 1 << 0,
193     RESPONSE_HEADERS = 1 << 1,
194     BLOCKING = 1 << 2,
195     ASYNC_BLOCKING = 1 << 3,
196     REQUEST_BODY = 1 << 4,
197     EXTRA_HEADERS = 1 << 5,
198   };
199 
200   static bool InitFromValue(content::BrowserContext* browser_context,
201                             const base::ListValue& value,
202                             int* extra_info_spec);
203 };
204 
205 // Data container for RequestCookies as defined in the declarative WebRequest
206 // API definition.
207 struct RequestCookie {
208   RequestCookie();
209   RequestCookie(RequestCookie&& other);
210   RequestCookie& operator=(RequestCookie&& other);
211   ~RequestCookie();
212 
213   bool operator==(const RequestCookie& other) const;
214 
215   RequestCookie Clone() const;
216 
217   base::Optional<std::string> name;
218   base::Optional<std::string> value;
219 
220   DISALLOW_COPY_AND_ASSIGN(RequestCookie);
221 };
222 
223 // Data container for ResponseCookies as defined in the declarative WebRequest
224 // API definition.
225 struct ResponseCookie {
226   ResponseCookie();
227   ResponseCookie(ResponseCookie&& other);
228   ResponseCookie& operator=(ResponseCookie&& other);
229   ~ResponseCookie();
230 
231   bool operator==(const ResponseCookie& other) const;
232 
233   ResponseCookie Clone() const;
234 
235   base::Optional<std::string> name;
236   base::Optional<std::string> value;
237   base::Optional<std::string> expires;
238   base::Optional<int> max_age;
239   base::Optional<std::string> domain;
240   base::Optional<std::string> path;
241   base::Optional<bool> secure;
242   base::Optional<bool> http_only;
243 
244   DISALLOW_COPY_AND_ASSIGN(ResponseCookie);
245 };
246 
247 // Data container for FilterResponseCookies as defined in the declarative
248 // WebRequest API definition.
249 struct FilterResponseCookie : ResponseCookie {
250   FilterResponseCookie();
251   FilterResponseCookie(FilterResponseCookie&& other);
252   FilterResponseCookie& operator=(FilterResponseCookie&& other);
253   ~FilterResponseCookie();
254 
255   FilterResponseCookie Clone() const;
256 
257   bool operator==(const FilterResponseCookie& other) const;
258 
259   base::Optional<int> age_lower_bound;
260   base::Optional<int> age_upper_bound;
261   base::Optional<bool> session_cookie;
262 
263   DISALLOW_COPY_AND_ASSIGN(FilterResponseCookie);
264 };
265 
266 enum CookieModificationType {
267   ADD,
268   EDIT,
269   REMOVE,
270 };
271 
272 struct RequestCookieModification {
273   RequestCookieModification();
274   RequestCookieModification(RequestCookieModification&& other);
275   RequestCookieModification& operator=(RequestCookieModification&& other);
276   ~RequestCookieModification();
277 
278   bool operator==(const RequestCookieModification& other) const;
279 
280   RequestCookieModification Clone() const;
281 
282   CookieModificationType type;
283   // Used for EDIT and REMOVE, nullopt otherwise.
284   base::Optional<RequestCookie> filter;
285   // Used for ADD and EDIT, nullopt otherwise.
286   base::Optional<RequestCookie> modification;
287 
288   DISALLOW_COPY_AND_ASSIGN(RequestCookieModification);
289 };
290 
291 struct ResponseCookieModification {
292   ResponseCookieModification();
293   ResponseCookieModification(ResponseCookieModification&& other);
294   ResponseCookieModification& operator=(ResponseCookieModification&& other);
295   ~ResponseCookieModification();
296 
297   bool operator==(const ResponseCookieModification& other) const;
298 
299   ResponseCookieModification Clone() const;
300 
301   CookieModificationType type;
302   // Used for EDIT and REMOVE, nullopt otherwise.
303   base::Optional<FilterResponseCookie> filter;
304   // Used for ADD and EDIT, nullopt otherwise.
305   base::Optional<ResponseCookie> modification;
306 
307   DISALLOW_COPY_AND_ASSIGN(ResponseCookieModification);
308 };
309 
310 using RequestCookieModifications = std::vector<RequestCookieModification>;
311 using ResponseCookieModifications = std::vector<ResponseCookieModification>;
312 
313 // Contains the modification an extension wants to perform on an event.
314 struct EventResponseDelta {
315   EventResponseDelta(const std::string& extension_id,
316                      const base::Time& extension_install_time);
317   EventResponseDelta(EventResponseDelta&& other);
318   EventResponseDelta& operator=(EventResponseDelta&& other);
319   ~EventResponseDelta();
320 
321   // ID of the extension that sent this response.
322   std::string extension_id;
323 
324   // The time that the extension was installed. Used for deciding order of
325   // precedence in case multiple extensions respond with conflicting
326   // decisions.
327   base::Time extension_install_time;
328 
329   // Response values. These are mutually exclusive.
330   bool cancel;
331   GURL new_url;
332 
333   // Newly introduced or overridden request headers.
334   net::HttpRequestHeaders modified_request_headers;
335 
336   // Keys of request headers to be deleted.
337   std::vector<std::string> deleted_request_headers;
338 
339   // Headers that were added to the response. A modification of a header
340   // corresponds to a deletion and subsequent addition of the new header.
341   ResponseHeaders added_response_headers;
342 
343   // Headers that were deleted from the response.
344   ResponseHeaders deleted_response_headers;
345 
346   // Authentication Credentials to use.
347   base::Optional<net::AuthCredentials> auth_credentials;
348 
349   // Modifications to cookies in request headers.
350   RequestCookieModifications request_cookie_modifications;
351 
352   // Modifications to cookies in response headers.
353   ResponseCookieModifications response_cookie_modifications;
354 
355   // Messages that shall be sent to the background/event/... pages of the
356   // extension.
357   std::set<std::string> messages_to_extension;
358 
359   DISALLOW_COPY_AND_ASSIGN(EventResponseDelta);
360 };
361 
362 using EventResponseDeltas = std::list<EventResponseDelta>;
363 
364 // Comparison operator that returns true if the extension that caused
365 // |a| was installed after the extension that caused |b|.
366 bool InDecreasingExtensionInstallationTimeOrder(const EventResponseDelta& a,
367                                                 const EventResponseDelta& b);
368 
369 // Converts a string to a list of integers, each in 0..255.
370 std::unique_ptr<base::ListValue> StringToCharList(const std::string& s);
371 
372 // Converts a list of integer values between 0 and 255 into a string |*out|.
373 // Returns true if the conversion was successful.
374 bool CharListToString(const base::ListValue* list, std::string* out);
375 
376 // The following functions calculate and return the modifications to requests
377 // commanded by extension handlers. All functions take the id of the extension
378 // that commanded a modification, the installation time of this extension (used
379 // for defining a precedence in conflicting modifications) and whether the
380 // extension requested to |cancel| the request. Other parameters depend on a
381 // the signal handler.
382 
383 EventResponseDelta CalculateOnBeforeRequestDelta(
384     const std::string& extension_id,
385     const base::Time& extension_install_time,
386     bool cancel,
387     const GURL& new_url);
388 EventResponseDelta CalculateOnBeforeSendHeadersDelta(
389     content::BrowserContext* browser_context,
390     const std::string& extension_id,
391     const base::Time& extension_install_time,
392     bool cancel,
393     net::HttpRequestHeaders* old_headers,
394     net::HttpRequestHeaders* new_headers,
395     int extra_info_spec);
396 EventResponseDelta CalculateOnHeadersReceivedDelta(
397     const std::string& extension_id,
398     const base::Time& extension_install_time,
399     bool cancel,
400     const GURL& old_url,
401     const GURL& new_url,
402     const net::HttpResponseHeaders* old_response_headers,
403     ResponseHeaders* new_response_headers,
404     int extra_info_spec);
405 EventResponseDelta CalculateOnAuthRequiredDelta(
406     const std::string& extension_id,
407     const base::Time& extension_install_time,
408     bool cancel,
409     base::Optional<net::AuthCredentials> auth_credentials);
410 
411 // These functions merge the responses (the |deltas|) of request handlers.
412 // The |deltas| need to be sorted in decreasing order of precedence of
413 // extensions. In case extensions had |deltas| that could not be honored, their
414 // IDs are reported in |conflicting_extensions|.
415 
416 // Stores in |*canceled_by_extension| whether any extension wanted to cancel the
417 // request, base::nullopt if none did, the extension id otherwise.
418 void MergeCancelOfResponses(
419     const EventResponseDeltas& deltas,
420     base::Optional<extensions::ExtensionId>* canceled_by_extension);
421 // Stores in |*new_url| the redirect request of the extension with highest
422 // precedence. Extensions that did not command to redirect the request are
423 // ignored in this logic.
424 void MergeRedirectUrlOfResponses(const GURL& url,
425                                  const EventResponseDeltas& deltas,
426                                  GURL* new_url,
427                                  IgnoredActions* ignored_actions);
428 // Stores in |*new_url| the redirect request of the extension with highest
429 // precedence. Extensions that did not command to redirect the request are
430 // ignored in this logic.
431 void MergeOnBeforeRequestResponses(const GURL& url,
432                                    const EventResponseDeltas& deltas,
433                                    GURL* new_url,
434                                    IgnoredActions* ignored_actions);
435 // Modifies the "Cookie" header in |request_headers| according to
436 // |deltas.request_cookie_modifications|. Conflicts are currently ignored
437 // silently.
438 void MergeCookiesInOnBeforeSendHeadersResponses(
439     const GURL& gurl,
440     const EventResponseDeltas& deltas,
441     net::HttpRequestHeaders* request_headers);
442 // Modifies the headers in |request_headers| according to |deltas|. Conflicts
443 // are tried to be resolved.
444 // Stores in |request_headers_modified| whether the request headers were
445 // modified.
446 // Any actions within |request.dnr_actions| which result in headers being
447 // modified are added to |matched_dnr_actions|.
448 void MergeOnBeforeSendHeadersResponses(
449     const extensions::WebRequestInfo& request,
450     const EventResponseDeltas& deltas,
451     net::HttpRequestHeaders* request_headers,
452     IgnoredActions* ignored_actions,
453     std::set<std::string>* removed_headers,
454     std::set<std::string>* set_headers,
455     bool* request_headers_modified,
456     std::vector<const extensions::declarative_net_request::RequestAction*>*
457         matched_dnr_actions);
458 // Modifies the "Set-Cookie" headers in |override_response_headers| according to
459 // |deltas.response_cookie_modifications|. If |override_response_headers| is
460 // NULL, a copy of |original_response_headers| is created. Conflicts are
461 // currently ignored silently.
462 void MergeCookiesInOnHeadersReceivedResponses(
463     const GURL& url,
464     const EventResponseDeltas& deltas,
465     const net::HttpResponseHeaders* original_response_headers,
466     scoped_refptr<net::HttpResponseHeaders>* override_response_headers);
467 // Stores a copy of |original_response_header| into |override_response_headers|
468 // that is modified according to |deltas|. If |deltas| does not instruct to
469 // modify the response headers, |override_response_headers| remains empty.
470 // Extension-initiated redirects are written to |override_response_headers|
471 // (to request redirection) and |*preserve_fragment_on_redirect_url| (to make
472 // sure that the URL provided by the extension isn't modified by having its
473 // fragment overwritten by that of the original URL). Stores in
474 // |response_headers_modified| whether the response headers were modified.
475 // Any actions within |request.dnr_actions| which result in headers being
476 // modified are added to |matched_dnr_actions|.
477 void MergeOnHeadersReceivedResponses(
478     const extensions::WebRequestInfo& request,
479     const EventResponseDeltas& deltas,
480     const net::HttpResponseHeaders* original_response_headers,
481     scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
482     GURL* preserve_fragment_on_redirect_url,
483     IgnoredActions* ignored_actions,
484     bool* response_headers_modified,
485     std::vector<const extensions::declarative_net_request::RequestAction*>*
486         matched_dnr_actions);
487 // Merge the responses of blocked onAuthRequired handlers. The first
488 // registered listener that supplies authentication credentials in a response,
489 // if any, will have its authentication credentials used. |request| must be
490 // non-NULL, and contain |deltas| that are sorted in decreasing order of
491 // precedence.
492 // Returns whether authentication credentials are set.
493 bool MergeOnAuthRequiredResponses(const EventResponseDeltas& deltas,
494                                   net::AuthCredentials* auth_credentials,
495                                   IgnoredActions* ignored_actions);
496 
497 // Triggers clearing each renderer's in-memory cache the next time it navigates.
498 void ClearCacheOnNavigation();
499 
500 // Converts the |name|, |value| pair of a http header to a HttpHeaders
501 // dictionary.
502 std::unique_ptr<base::DictionaryValue> CreateHeaderDictionary(
503     const std::string& name,
504     const std::string& value);
505 
506 // Returns whether a request header should be hidden from listeners.
507 bool ShouldHideRequestHeader(content::BrowserContext* browser_context,
508                              int extra_info_spec,
509                              const std::string& name);
510 
511 // Returns whether a response header should be hidden from listeners.
512 bool ShouldHideResponseHeader(int extra_info_spec, const std::string& name);
513 
514 }  // namespace extension_web_request_api_helpers
515 
516 #endif  // EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
517