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