File: web_request_api_helpers.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (522 lines) | stat: -rw-r--r-- 18,433 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Helper classes and functions used for the WebRequest API.

#ifndef EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_
#define EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_

#include <list>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "base/values.h"
#include "extensions/common/api/web_request.h"
#include "extensions/common/extension_id.h"
#include "net/base/auth.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "url/gurl.h"

namespace content {
class BrowserContext;
}

namespace extensions {
class Extension;
struct WebRequestInfo;

namespace declarative_net_request {
struct RequestAction;
}  // namespace declarative_net_request

}  // namespace extensions

namespace extension_web_request_api_helpers {

using ResponseHeader = std::pair<std::string, std::string>;
using ResponseHeaders = std::vector<ResponseHeader>;

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class RequestHeaderType {
  kNone = 0,
  kOther = 1,
  kAccept = 2,
  kAcceptCharset = 3,
  kAcceptEncoding = 4,
  kAcceptLanguage = 5,
  kAccessControlRequestHeaders = 6,
  kAccessControlRequestMethod = 7,
  kAuthorization = 8,
  kCacheControl = 9,
  kConnection = 10,
  kContentEncoding = 11,
  kContentLanguage = 12,
  kContentLength = 13,
  kContentLocation = 14,
  kContentType = 15,
  kCookie = 16,
  kDate = 17,
  kDnt = 18,
  kEarlyData = 19,
  kExpect = 20,
  kForwarded = 21,
  kFrom = 22,
  kHost = 23,
  kIfMatch = 24,
  kIfModifiedSince = 25,
  kIfNoneMatch = 26,
  kIfRange = 27,
  kIfUnmodifiedSince = 28,
  kKeepAlive = 29,
  kOrigin = 30,
  kPragma = 31,
  kProxyAuthorization = 32,
  kProxyConnection = 33,
  kRange = 34,
  kReferer = 35,
  //  kSecOriginPolicy = 36, // no longer shipping
  kTe = 37,
  kTransferEncoding = 38,
  kUpgrade = 39,
  kUpgradeInsecureRequests = 40,
  kUserAgent = 41,
  kVia = 42,
  kWarning = 43,
  kXForwardedFor = 44,
  kXForwardedHost = 45,
  kXForwardedProto = 46,
  kMaxValue = kXForwardedProto,
};

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class ResponseHeaderType {
  kNone = 0,
  kOther = 1,
  kAcceptPatch = 2,
  kAcceptRanges = 3,
  kAccessControlAllowCredentials = 4,
  kAccessControlAllowHeaders = 5,
  kAccessControlAllowMethods = 6,
  kAccessControlAllowOrigin = 7,
  kAccessControlExposeHeaders = 8,
  kAccessControlMaxAge = 9,
  kAge = 10,
  kAllow = 11,
  kAltSvc = 12,
  kCacheControl = 13,
  kClearSiteData = 14,
  kConnection = 15,
  kContentDisposition = 16,
  kContentEncoding = 17,
  kContentLanguage = 18,
  kContentLength = 19,
  kContentLocation = 20,
  kContentRange = 21,
  kContentSecurityPolicy = 22,
  kContentSecurityPolicyReportOnly = 23,
  kContentType = 24,
  kDate = 25,
  kETag = 26,
  kExpectCT = 27,
  kExpires = 28,
  kFeaturePolicy = 29,
  kKeepAlive = 30,
  kLargeAllocation = 31,
  kLastModified = 32,
  kLocation = 33,
  kPragma = 34,
  kProxyAuthenticate = 35,
  kProxyConnection = 36,
  kPublicKeyPins = 37,
  kPublicKeyPinsReportOnly = 38,
  kReferrerPolicy = 39,
  kRefresh = 40,
  kRetryAfter = 41,
  kSecWebSocketAccept = 42,
  kServer = 43,
  kServerTiming = 44,
  kSetCookie = 45,
  kSourceMap = 46,
  kStrictTransportSecurity = 47,
  kTimingAllowOrigin = 48,
  kTk = 49,
  kTrailer = 50,
  kTransferEncoding = 51,
  kUpgrade = 52,
  kVary = 53,
  kVia = 54,
  kWarning = 55,
  kWWWAuthenticate = 56,
  kXContentTypeOptions = 57,
  kXDNSPrefetchControl = 58,
  kXFrameOptions = 59,
  kXXSSProtection = 60,
  kMaxValue = kXXSSProtection
};

struct IgnoredAction {
  IgnoredAction(extensions::ExtensionId extension_id,
                extensions::api::web_request::IgnoredActionType action_type);
  IgnoredAction(const IgnoredAction&) = delete;
  IgnoredAction(IgnoredAction&& rhs);
  IgnoredAction& operator=(const IgnoredAction&) = delete;

  extensions::ExtensionId extension_id;
  extensions::api::web_request::IgnoredActionType action_type;
};

using IgnoredActions = std::vector<IgnoredAction>;

// Internal representation of the extraInfoSpec parameter on webRequest
// events, used to specify extra information to be included with network
// events.
struct ExtraInfoSpec {
  enum Flags {
    REQUEST_HEADERS = 1 << 0,
    RESPONSE_HEADERS = 1 << 1,
    BLOCKING = 1 << 2,
    ASYNC_BLOCKING = 1 << 3,
    REQUEST_BODY = 1 << 4,
    EXTRA_HEADERS = 1 << 5,
  };

  static bool InitFromValue(content::BrowserContext* browser_context,
                            const base::Value& value,
                            int* extra_info_spec);
};

// Data container for RequestCookies as defined in the declarative WebRequest
// API definition.
struct RequestCookie {
  RequestCookie();
  RequestCookie(const RequestCookie&) = delete;
  RequestCookie(RequestCookie&& other);
  RequestCookie& operator=(const RequestCookie&) = delete;
  RequestCookie& operator=(RequestCookie&& other);
  ~RequestCookie();

  bool operator==(const RequestCookie& other) const;

  RequestCookie Clone() const;

  std::optional<std::string> name;
  std::optional<std::string> value;
};

// Data container for ResponseCookies as defined in the declarative WebRequest
// API definition.
struct ResponseCookie {
  ResponseCookie();
  ResponseCookie(const ResponseCookie&) = delete;
  ResponseCookie(ResponseCookie&& other);
  ResponseCookie& operator=(const ResponseCookie&) = delete;
  ResponseCookie& operator=(ResponseCookie&& other);
  ~ResponseCookie();

  bool operator==(const ResponseCookie& other) const;

  ResponseCookie Clone() const;

  std::optional<std::string> name;
  std::optional<std::string> value;
  std::optional<std::string> expires;
  std::optional<int> max_age;
  std::optional<std::string> domain;
  std::optional<std::string> path;
  std::optional<bool> secure;
  std::optional<bool> http_only;
};

// Data container for FilterResponseCookies as defined in the declarative
// WebRequest API definition.
struct FilterResponseCookie : ResponseCookie {
  FilterResponseCookie();
  FilterResponseCookie(const FilterResponseCookie&) = delete;
  FilterResponseCookie(FilterResponseCookie&& other);
  FilterResponseCookie& operator=(const FilterResponseCookie&) = delete;
  FilterResponseCookie& operator=(FilterResponseCookie&& other);
  ~FilterResponseCookie();

  FilterResponseCookie Clone() const;

  bool operator==(const FilterResponseCookie& other) const;

  std::optional<int> age_lower_bound;
  std::optional<int> age_upper_bound;
  std::optional<bool> session_cookie;
};

enum CookieModificationType {
  ADD,
  EDIT,
  REMOVE,
};

struct RequestCookieModification {
  RequestCookieModification();
  RequestCookieModification(const RequestCookieModification&) = delete;
  RequestCookieModification(RequestCookieModification&& other);
  RequestCookieModification& operator=(const RequestCookieModification&) =
      delete;
  RequestCookieModification& operator=(RequestCookieModification&& other);
  ~RequestCookieModification();

  bool operator==(const RequestCookieModification& other) const;

  RequestCookieModification Clone() const;

  CookieModificationType type;
  // Used for EDIT and REMOVE, nullopt otherwise.
  std::optional<RequestCookie> filter;
  // Used for ADD and EDIT, nullopt otherwise.
  std::optional<RequestCookie> modification;
};

struct ResponseCookieModification {
  ResponseCookieModification();
  ResponseCookieModification(const ResponseCookieModification&) = delete;
  ResponseCookieModification(ResponseCookieModification&& other);
  ResponseCookieModification& operator=(const ResponseCookieModification&) =
      delete;
  ResponseCookieModification& operator=(ResponseCookieModification&& other);
  ~ResponseCookieModification();

  bool operator==(const ResponseCookieModification& other) const;

  ResponseCookieModification Clone() const;

  CookieModificationType type;
  // Used for EDIT and REMOVE, nullopt otherwise.
  std::optional<FilterResponseCookie> filter;
  // Used for ADD and EDIT, nullopt otherwise.
  std::optional<ResponseCookie> modification;
};

using RequestCookieModifications = std::vector<RequestCookieModification>;
using ResponseCookieModifications = std::vector<ResponseCookieModification>;

// Contains the modification an extension wants to perform on an event.
struct EventResponseDelta {
  EventResponseDelta(const extensions::ExtensionId& extension_id,
                     const base::Time& extension_install_time);
  EventResponseDelta(const EventResponseDelta&) = delete;
  EventResponseDelta(EventResponseDelta&& other);
  EventResponseDelta& operator=(const EventResponseDelta&) = delete;
  EventResponseDelta& operator=(EventResponseDelta&& other);
  ~EventResponseDelta();

  // ID of the extension that sent this response.
  extensions::ExtensionId extension_id;

  // The time that the extension was installed. Used for deciding order of
  // precedence in case multiple extensions respond with conflicting
  // decisions.
  base::Time extension_install_time;

  // Response values. These are mutually exclusive.
  bool cancel;
  GURL new_url;

  // Newly introduced or overridden request headers.
  net::HttpRequestHeaders modified_request_headers;

  // Keys of request headers to be deleted.
  std::vector<std::string> deleted_request_headers;

  // Headers that were added to the response. A modification of a header
  // corresponds to a deletion and subsequent addition of the new header.
  ResponseHeaders added_response_headers;

  // Headers that were deleted from the response.
  ResponseHeaders deleted_response_headers;

  // Authentication Credentials to use.
  std::optional<net::AuthCredentials> auth_credentials;

  // Modifications to cookies in request headers.
  RequestCookieModifications request_cookie_modifications;

  // Modifications to cookies in response headers.
  ResponseCookieModifications response_cookie_modifications;

  // Messages that shall be sent to the background/event/... pages of the
  // extension.
  std::set<std::string> messages_to_extension;
};

using EventResponseDeltas = std::list<EventResponseDelta>;

// Comparison operator that returns true if the extension that caused
// `a` was installed after the extension that caused `b`.
bool InDecreasingExtensionInstallationTimeOrder(const EventResponseDelta& a,
                                                const EventResponseDelta& b);

// Converts a string to a list of integers, each in 0..255.
base::Value::List StringToCharList(const std::string& s);

// Converts a list of integer values between 0 and 255 into a string |*out|.
// Returns true if the conversion was successful.
bool CharListToString(const base::Value::List& list, std::string* out);

// The following functions calculate and return the modifications to requests
// commanded by extension handlers. All functions take the id of the extension
// that commanded a modification, the installation time of this extension (used
// for defining a precedence in conflicting modifications) and whether the
// extension requested to `cancel` the request. Other parameters depend on a
// the signal handler.

EventResponseDelta CalculateOnBeforeRequestDelta(
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    const GURL& new_url);
EventResponseDelta CalculateOnBeforeSendHeadersDelta(
    content::BrowserContext* browser_context,
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    net::HttpRequestHeaders* old_headers,
    net::HttpRequestHeaders* new_headers,
    int extra_info_spec);
EventResponseDelta CalculateOnHeadersReceivedDelta(
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    const GURL& old_url,
    const GURL& new_url,
    const net::HttpResponseHeaders* old_response_headers,
    ResponseHeaders* new_response_headers,
    int extra_info_spec);
EventResponseDelta CalculateOnAuthRequiredDelta(
    const extensions::ExtensionId& extension_id,
    const base::Time& extension_install_time,
    bool cancel,
    std::optional<net::AuthCredentials> auth_credentials);

// These functions merge the responses (the `deltas`) of request handlers.
// The `deltas` need to be sorted in decreasing order of precedence of
// extensions. In case extensions had `deltas` that could not be honored, their
// IDs are reported in `conflicting_extensions`.

// Stores in |*canceled_by_extension| whether any extension wanted to cancel the
// request, std::nullopt if none did, the extension id otherwise.
void MergeCancelOfResponses(
    const EventResponseDeltas& deltas,
    std::optional<extensions::ExtensionId>* canceled_by_extension);
// Stores in |*new_url| the redirect request of the extension with highest
// precedence. Extensions that did not command to redirect the request are
// ignored in this logic.
void MergeRedirectUrlOfResponses(
    const GURL& url,
    const EventResponseDeltas& deltas,
    GURL* new_url,
    std::optional<extensions::ExtensionId>* extension_id,
    IgnoredActions* ignored_actions);
// Stores in |*new_url| the redirect request of the extension with highest
// precedence. Extensions that did not command to redirect the request are
// ignored in this logic.
void MergeOnBeforeRequestResponses(
    const GURL& url,
    const EventResponseDeltas& deltas,
    GURL* new_url,
    std::optional<extensions::ExtensionId>* extension_id,
    IgnoredActions* ignored_actions);
// Modifies the "Cookie" header in `request_headers` according to
// |deltas.request_cookie_modifications|. Conflicts are currently ignored
// silently.
void MergeCookiesInOnBeforeSendHeadersResponses(
    const GURL& gurl,
    const EventResponseDeltas& deltas,
    net::HttpRequestHeaders* request_headers);
// Modifies the headers in `request_headers` according to `deltas`. Conflicts
// are tried to be resolved.
// Stores in `request_headers_modified` whether the request headers were
// modified.
// Any actions within |request.dnr_actions| which result in headers being
// modified are added to `matched_dnr_actions`.
void MergeOnBeforeSendHeadersResponses(
    const extensions::WebRequestInfo& request,
    const EventResponseDeltas& deltas,
    net::HttpRequestHeaders* request_headers,
    IgnoredActions* ignored_actions,
    std::set<std::string>* removed_headers,
    std::set<std::string>* set_headers,
    bool* request_headers_modified,
    std::vector<const extensions::declarative_net_request::RequestAction*>*
        matched_dnr_actions);
// Modifies the "Set-Cookie" headers in `override_response_headers` according to
// |deltas.response_cookie_modifications|. If `override_response_headers` is
// NULL, a copy of `original_response_headers` is created. Conflicts are
// currently ignored silently.
void MergeCookiesInOnHeadersReceivedResponses(
    const GURL& url,
    const EventResponseDeltas& deltas,
    const net::HttpResponseHeaders* original_response_headers,
    scoped_refptr<net::HttpResponseHeaders>* override_response_headers);
// Stores a copy of `original_response_header` into `override_response_headers`
// that is modified according to `deltas`. If `deltas` does not instruct to
// modify the response headers, `override_response_headers` remains empty.
// Extension-initiated redirects are written to `override_response_headers`
// (to request redirection) and |*preserve_fragment_on_redirect_url| (to make
// sure that the URL provided by the extension isn't modified by having its
// fragment overwritten by that of the original URL). Stores in
// `response_headers_modified` whether the response headers were modified.
// Any actions within |request.dnr_actions| which result in headers being
// modified are added to `matched_dnr_actions`.
void MergeOnHeadersReceivedResponses(
    const extensions::WebRequestInfo& request,
    const EventResponseDeltas& deltas,
    const net::HttpResponseHeaders* original_response_headers,
    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
    GURL* preserve_fragment_on_redirect_url,
    std::optional<extensions::ExtensionId>* extenion_id,
    IgnoredActions* ignored_actions,
    bool* response_headers_modified,
    std::vector<const extensions::declarative_net_request::RequestAction*>*
        matched_dnr_actions);
// Merge the responses of blocked onAuthRequired handlers. The first
// registered listener that supplies authentication credentials in a response,
// if any, will have its authentication credentials used. `request` must be
// non-NULL, and contain `deltas` that are sorted in decreasing order of
// precedence.
// Returns whether authentication credentials are set.
bool MergeOnAuthRequiredResponses(const EventResponseDeltas& deltas,
                                  net::AuthCredentials* auth_credentials,
                                  IgnoredActions* ignored_actions);

// Triggers clearing any back-forward caches and each renderer's in-memory cache
// the next time it navigates.
void ClearCacheOnNavigation();

// Converts the `name`, `value` pair of a http header to a HttpHeaders
// dictionary.
base::Value::Dict CreateHeaderDictionary(const std::string& name,
                                         const std::string& value);

// Returns whether a request header should be hidden from listeners.
bool ShouldHideRequestHeader(content::BrowserContext* browser_context,
                             int extra_info_spec,
                             const std::string& name);

// Returns whether a response header should be hidden from listeners.
bool ShouldHideResponseHeader(int extra_info_spec, const std::string& name);

// "Redirects" a request to `new_url` after the response has started by setting
// the appropriate headers in `override_response_headers`.
void RedirectRequestAfterHeadersReceived(
    const GURL& new_url,
    net::HttpResponseHeaders& override_response_headers,
    GURL* preserve_fragment_on_redirect_url);

}  // namespace extension_web_request_api_helpers

#endif  // EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_API_HELPERS_H_