summaryrefslogtreecommitdiff
path: root/chromium/net/url_request/url_request_http_job.h
blob: 9d9e968d01a86e6ea5533cb1e539e70757e797aa (plain)
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
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_URL_REQUEST_URL_REQUEST_HTTP_JOB_H_
#define NET_URL_REQUEST_URL_REQUEST_HTTP_JOB_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "net/base/auth.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_error_details.h"
#include "net/base/net_export.h"
#include "net/base/privacy_mode.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_partition_key.h"
#include "net/cookies/first_party_set_metadata.h"
#include "net/http/http_request_info.h"
#include "net/socket/connection_attempts.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_throttler_entry_interface.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace net {

class HttpRequestHeaders;
class HttpResponseHeaders;
class HttpResponseInfo;
class HttpTransaction;
class HttpUserAgentSettings;
class SSLPrivateKey;
struct TransportInfo;
class UploadDataStream;

// A URLRequestJob subclass that is built on top of HttpTransaction. It
// provides an implementation for both HTTP and HTTPS.
class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
 public:
  // Creates URLRequestJob for the specified HTTP, HTTPS, WS, or WSS URL.
  // Returns a job that returns a redirect in the case of HSTS, and returns a
  // job that fails for unencrypted requests if current settings dont allow
  // them. Never returns nullptr.
  static std::unique_ptr<URLRequestJob> Create(URLRequest* request);

  URLRequestHttpJob(const URLRequestHttpJob&) = delete;
  URLRequestHttpJob& operator=(const URLRequestHttpJob&) = delete;

  void SetRequestHeadersCallback(RequestHeadersCallback callback) override;
  void SetEarlyResponseHeadersCallback(
      ResponseHeadersCallback callback) override;
  void SetResponseHeadersCallback(ResponseHeadersCallback callback) override;

 protected:
  URLRequestHttpJob(URLRequest* request,
                    const HttpUserAgentSettings* http_user_agent_settings);

  ~URLRequestHttpJob() override;

  // Overridden from URLRequestJob:
  void SetPriority(RequestPriority priority) override;
  void Start() override;
  void Kill() override;
  ConnectionAttempts GetConnectionAttempts() const override;
  void CloseConnectionOnDestruction() override;
  std::unique_ptr<SourceStream> SetUpSourceStream() override;

  RequestPriority priority() const {
    return priority_;
  }

 private:
  // For CookieRequestScheme histogram enum.
  FRIEND_TEST_ALL_PREFIXES(URLRequestHttpJobTest,
                           CookieSchemeRequestSchemeHistogram);

  enum CompletionCause {
    ABORTED,
    FINISHED
  };

  // Used to indicate which kind of cookies are sent on which kind of requests,
  // for use in histograms. A (non)secure set cookie means that the cookie was
  // originally set by a (non)secure url. A (non)secure request means that the
  // request url is (non)secure. An unset cookie scheme means that the cookie's
  // source scheme was marked as "Unset" and thus cannot be compared  with the
  // request.
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  enum class CookieRequestScheme {
    kUnsetCookieScheme = 0,
    kNonsecureSetNonsecureRequest,
    kSecureSetSecureRequest,
    kNonsecureSetSecureRequest,
    kSecureSetNonsecureRequest,

    kMaxValue = kSecureSetNonsecureRequest  // Keep as the last value.
  };

  typedef base::RefCountedData<bool> SharedBoolean;

  // Shadows URLRequestJob's version of this method so we can grab cookies.
  void NotifyHeadersComplete();

  void DestroyTransaction();

  // Computes the PrivacyMode that should be associated with this leg of the
  // request. Must be recomputed on redirects.
  PrivacyMode DeterminePrivacyMode() const;

  void AddExtraHeaders();
  void AddCookieHeaderAndStart();
  void AnnotateAndMoveUserBlockedCookies(
      CookieAccessResultList& maybe_included_cookies,
      CookieAccessResultList& excluded_cookies) const;
  void SaveCookiesAndNotifyHeadersComplete(int result);

  // Processes the Strict-Transport-Security header, if one exists.
  void ProcessStrictTransportSecurityHeader();

  // Processes the Expect-CT header, if one exists. This header
  // indicates that the server wants the user agent to send a report
  // when a connection violates the Expect CT policy.
  void ProcessExpectCTHeader();

  // |result| should be OK, or the request is canceled.
  void OnHeadersReceivedCallback(int result);
  void OnStartCompleted(int result);
  void OnReadCompleted(int result);
  void NotifyBeforeStartTransactionCallback(
      int result,
      const absl::optional<HttpRequestHeaders>& headers);
  // This just forwards the call to URLRequestJob::NotifyConnected().
  // We need it because that method is protected and cannot be bound in a
  // callback in this class.
  int NotifyConnectedCallback(const TransportInfo& info,
                              CompletionOnceCallback callback);

  void RestartTransactionWithAuth(const AuthCredentials& credentials);

  // Overridden from URLRequestJob:
  void SetUpload(UploadDataStream* upload) override;
  void SetExtraRequestHeaders(const HttpRequestHeaders& headers) override;
  LoadState GetLoadState() const override;
  bool GetMimeType(std::string* mime_type) const override;
  bool GetCharset(std::string* charset) override;
  void GetResponseInfo(HttpResponseInfo* info) override;
  void GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
  bool GetTransactionRemoteEndpoint(IPEndPoint* endpoint) const override;
  int GetResponseCode() const override;
  void PopulateNetErrorDetails(NetErrorDetails* details) const override;
  bool CopyFragmentOnRedirect(const GURL& location) const override;
  bool IsSafeRedirect(const GURL& location) override;
  bool NeedsAuth() override;
  std::unique_ptr<AuthChallengeInfo> GetAuthChallengeInfo() override;
  void SetAuth(const AuthCredentials& credentials) override;
  void CancelAuth() override;
  void ContinueWithCertificate(
      scoped_refptr<X509Certificate> client_cert,
      scoped_refptr<SSLPrivateKey> client_private_key) override;
  void ContinueDespiteLastError() override;
  int ReadRawData(IOBuffer* buf, int buf_size) override;
  int64_t GetTotalReceivedBytes() const override;
  int64_t GetTotalSentBytes() const override;
  void DoneReading() override;
  void DoneReadingRedirectResponse() override;

  IPEndPoint GetResponseRemoteEndpoint() const override;
  void NotifyURLRequestDestroyed() override;

  void RecordTimer();
  void ResetTimer();

  // Starts the transaction if extensions using the webrequest API do not
  // object.
  void StartTransaction();
  // If |result| is OK, calls StartTransactionInternal. Otherwise notifies
  // cancellation.
  void MaybeStartTransactionInternal(int result);
  void StartTransactionInternal();

  void RecordCompletionHistograms(CompletionCause reason);
  void DoneWithRequest(CompletionCause reason);

  // Callback functions for Cookie Monster
  void SetCookieHeaderAndStart(const CookieOptions& options,
                               const CookieAccessResultList& cookie_list,
                               const CookieAccessResultList& excluded_list);

  // Another Cookie Monster callback
  void OnSetCookieResult(const CookieOptions& options,
                         absl::optional<CanonicalCookie> cookie,
                         std::string cookie_string,
                         CookieAccessResult access_result);
  int num_cookie_lines_left_ = 0;
  CookieAndLineAccessResultList set_cookie_access_result_list_;

  // Some servers send the body compressed, but specify the content length as
  // the uncompressed size. If this is the case, we return true in order
  // to request to work around this non-adherence to the HTTP standard.
  // |rv| is the standard return value of a read function indicating the number
  // of bytes read or, if negative, an error code.
  bool ShouldFixMismatchedContentLength(int rv) const;

  // Returns the effective response headers, considering that they may be
  // overridden by `override_response_headers_` or
  // `override_response_info_::headers`.
  HttpResponseHeaders* GetResponseHeaders() const;

  // Called after getting the FirstPartySetMetadata during Start for this job.
  void OnGotFirstPartySetMetadata(
      FirstPartySetMetadata first_party_set_metadata);

  // Returns true iff this request leg should include the Cookie header. Note
  // that cookies may still be eventually blocked by the CookieAccessDelegate
  // even if this method returns true.
  bool ShouldAddCookieHeader() const;

  // Returns true if partitioned cookies are enabled and can be accessed and/or
  // set.
  bool IsPartitionedCookiesEnabled() const;

  RequestPriority priority_ = DEFAULT_PRIORITY;

  HttpRequestInfo request_info_;

  // Used for any logic, e.g. DNS-based scheme upgrade, that needs to synthesize
  // response info to override the real response info. Transaction should be
  // cleared before setting.
  std::unique_ptr<HttpResponseInfo> override_response_info_;

  // Auth states for proxy and origin server.
  AuthState proxy_auth_state_ = AUTH_STATE_DONT_NEED_AUTH;
  AuthState server_auth_state_ = AUTH_STATE_DONT_NEED_AUTH;
  AuthCredentials auth_credentials_;

  bool read_in_progress_ = false;

  std::unique_ptr<HttpTransaction> transaction_;

  // This needs to be declared after `transaction_` and
  // `override_response_info_` because `response_info_` holds a pointer that's
  // itself owned by one of those, so `response_info_` needs to be destroyed
  // first.
  raw_ptr<const HttpResponseInfo> response_info_ = nullptr;

  // This is used to supervise traffic and enforce exponential
  // back-off. May be NULL.
  scoped_refptr<URLRequestThrottlerEntryInterface> throttling_entry_;

  base::Time request_creation_time_;

  // True when we are done doing work.
  bool done_ = false;

  // The start time for the job, ignoring re-starts.
  base::TimeTicks start_time_;

  // When the transaction finished reading the request headers.
  base::TimeTicks receive_headers_end_;

  // We allow the network delegate to modify a copy of the response headers.
  // This prevents modifications of headers that are shared with the underlying
  // layers of the network stack.
  scoped_refptr<HttpResponseHeaders> override_response_headers_;

  // Ordinarily the original URL's fragment is copied during redirects, unless
  // the destination URL already has one. However, the NetworkDelegate can
  // override this behavior by setting |preserve_fragment_on_redirect_url_|:
  // * If set to absl::nullopt, the default behavior is used.
  // * If the final URL in the redirect chain matches
  //     |preserve_fragment_on_redirect_url_|, its fragment unchanged. So this
  //     is basically a way for the embedder to force a redirect not to copy the
  //     original URL's fragment when the original URL had one.
  absl::optional<GURL> preserve_fragment_on_redirect_url_;

  // Flag used to verify that |this| is not deleted while we are awaiting
  // a callback from the NetworkDelegate. Used as a fail-fast mechanism.
  // True if we are waiting a callback and
  // NetworkDelegate::NotifyURLRequestDestroyed has not been called, yet,
  // to inform the NetworkDelegate that it may not call back.
  bool awaiting_callback_ = false;

  raw_ptr<const HttpUserAgentSettings> http_user_agent_settings_;

  // Keeps track of total received bytes over the network from transactions used
  // by this job that have already been destroyed.
  int64_t total_received_bytes_from_previous_transactions_ = 0;
  // Keeps track of total sent bytes over the network from transactions used by
  // this job that have already been destroyed.
  int64_t total_sent_bytes_from_previous_transactions_ = 0;

  RequestHeadersCallback request_headers_callback_;
  ResponseHeadersCallback early_response_headers_callback_;
  ResponseHeadersCallback response_headers_callback_;

  // The First-Party Set metadata associated with this job. Set when the job is
  // started.
  FirstPartySetMetadata first_party_set_metadata_;

  // The cookie partition key for the request. Partitioned cookies should be set
  // using this key and only partitioned cookies with this partition key should
  // be sent. The cookie partition key is optional(nullopt) if cookie
  // partitioning is not enabled, or if the NIK has no top-frame site.
  //
  // Unpartitioned cookies are unaffected by this field.
  //
  // The two layers of `optional` are because the `cookie_partition_key_` is
  // lazily computed, and might be "nothing". We want to be able to distinguish
  // "uncomputed" from "nothing".
  absl::optional<absl::optional<CookiePartitionKey>> cookie_partition_key_;

  base::WeakPtrFactory<URLRequestHttpJob> weak_factory_{this};
};

}  // namespace net

#endif  // NET_URL_REQUEST_URL_REQUEST_HTTP_JOB_H_