• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/url_request/url_request_http_job.h"
6 
7 #include <algorithm>
8 #include <iterator>
9 #include <memory>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/base_switches.h"
14 #include "base/check_op.h"
15 #include "base/command_line.h"
16 #include "base/compiler_specific.h"
17 #include "base/containers/adapters.h"
18 #include "base/feature_list.h"
19 #include "base/file_version_info.h"
20 #include "base/functional/bind.h"
21 #include "base/functional/callback_helpers.h"
22 #include "base/location.h"
23 #include "base/memory/ptr_util.h"
24 #include "base/metrics/field_trial.h"
25 #include "base/metrics/histogram_functions.h"
26 #include "base/metrics/histogram_macros.h"
27 #include "base/numerics/safe_conversions.h"
28 #include "base/rand_util.h"
29 #include "base/strings/string_number_conversions.h"
30 #include "base/strings/string_util.h"
31 #include "base/strings/stringprintf.h"
32 #include "base/task/single_thread_task_runner.h"
33 #include "base/time/time.h"
34 #include "base/types/optional_util.h"
35 #include "base/values.h"
36 #include "build/build_config.h"
37 #include "net/base/host_port_pair.h"
38 #include "net/base/http_user_agent_settings.h"
39 #include "net/base/load_flags.h"
40 #include "net/base/net_errors.h"
41 #include "net/base/network_anonymization_key.h"
42 #include "net/base/network_delegate.h"
43 #include "net/base/network_isolation_key.h"
44 #include "net/base/privacy_mode.h"
45 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
46 #include "net/base/schemeful_site.h"
47 #include "net/base/trace_constants.h"
48 #include "net/base/tracing.h"
49 #include "net/base/url_util.h"
50 #include "net/cert/cert_status_flags.h"
51 #include "net/cert/ct_policy_status.h"
52 #include "net/cert/known_roots.h"
53 #include "net/cookies/canonical_cookie.h"
54 #include "net/cookies/cookie_access_delegate.h"
55 #include "net/cookies/cookie_constants.h"
56 #include "net/cookies/cookie_store.h"
57 #include "net/cookies/cookie_util.h"
58 #include "net/cookies/parsed_cookie.h"
59 #include "net/filter/brotli_source_stream.h"
60 #include "net/filter/filter_source_stream.h"
61 #include "net/filter/gzip_source_stream.h"
62 #include "net/filter/source_stream.h"
63 #include "net/filter/zstd_source_stream.h"
64 #include "net/first_party_sets/first_party_set_entry.h"
65 #include "net/first_party_sets/first_party_set_metadata.h"
66 #include "net/first_party_sets/first_party_sets_cache_filter.h"
67 #include "net/http/http_content_disposition.h"
68 #include "net/http/http_log_util.h"
69 #include "net/http/http_network_session.h"
70 #include "net/http/http_request_headers.h"
71 #include "net/http/http_response_headers.h"
72 #include "net/http/http_response_info.h"
73 #include "net/http/http_status_code.h"
74 #include "net/http/http_transaction.h"
75 #include "net/http/http_transaction_factory.h"
76 #include "net/http/http_util.h"
77 #include "net/http/transport_security_state.h"
78 #include "net/log/net_log.h"
79 #include "net/log/net_log_event_type.h"
80 #include "net/log/net_log_values.h"
81 #include "net/log/net_log_with_source.h"
82 #include "net/nqe/network_quality_estimator.h"
83 #include "net/proxy_resolution/proxy_info.h"
84 #include "net/proxy_resolution/proxy_resolution_service.h"
85 #include "net/proxy_resolution/proxy_retry_info.h"
86 #include "net/ssl/ssl_cert_request_info.h"
87 #include "net/ssl/ssl_config_service.h"
88 #include "net/ssl/ssl_connection_status_flags.h"
89 #include "net/url_request/clear_site_data.h"
90 #include "net/url_request/redirect_util.h"
91 #include "net/url_request/url_request.h"
92 #include "net/url_request/url_request_context.h"
93 #include "net/url_request/url_request_error_job.h"
94 #include "net/url_request/url_request_job_factory.h"
95 #include "net/url_request/url_request_redirect_job.h"
96 #include "net/url_request/url_request_throttler_manager.h"
97 #include "net/url_request/websocket_handshake_userdata_key.h"
98 #include "third_party/abseil-cpp/absl/types/optional.h"
99 #include "url/gurl.h"
100 #include "url/origin.h"
101 #include "url/url_constants.h"
102 
103 #if BUILDFLAG(IS_ANDROID)
104 #include "net/android/network_library.h"
105 #endif
106 
107 namespace {
108 
FirstPartySetMetadataNetLogParams(const net::FirstPartySetMetadata & first_party_set_metadata,const int64_t * const fps_cache_filter)109 base::Value::Dict FirstPartySetMetadataNetLogParams(
110     const net::FirstPartySetMetadata& first_party_set_metadata,
111     const int64_t* const fps_cache_filter) {
112   base::Value::Dict dict;
113   auto entry_or_empty =
114       [](const absl::optional<net::FirstPartySetEntry>& entry) -> std::string {
115     return entry.has_value() ? entry->GetDebugString() : "none";
116   };
117 
118   dict.Set("cache_filter",
119            fps_cache_filter ? base::NumberToString(*fps_cache_filter) : "none");
120   dict.Set("frame_entry",
121            entry_or_empty(first_party_set_metadata.frame_entry()));
122   dict.Set("top_frame_primary",
123            entry_or_empty(first_party_set_metadata.top_frame_entry()));
124   return dict;
125 }
126 
CookieInclusionStatusNetLogParams(const std::string & operation,const std::string & cookie_name,const std::string & cookie_domain,const std::string & cookie_path,const net::CookieInclusionStatus & status,net::NetLogCaptureMode capture_mode)127 base::Value::Dict CookieInclusionStatusNetLogParams(
128     const std::string& operation,
129     const std::string& cookie_name,
130     const std::string& cookie_domain,
131     const std::string& cookie_path,
132     const net::CookieInclusionStatus& status,
133     net::NetLogCaptureMode capture_mode) {
134   base::Value::Dict dict;
135   dict.Set("operation", operation);
136   dict.Set("status", status.GetDebugString());
137   if (net::NetLogCaptureIncludesSensitive(capture_mode)) {
138     if (!cookie_name.empty())
139       dict.Set("name", cookie_name);
140     if (!cookie_domain.empty())
141       dict.Set("domain", cookie_domain);
142     if (!cookie_path.empty())
143       dict.Set("path", cookie_path);
144   }
145   return dict;
146 }
147 
148 // Records details about the most-specific trust anchor in |spki_hashes|,
149 // which is expected to be ordered with the leaf cert first and the root cert
150 // last. This complements the per-verification histogram
151 // Net.Certificate.TrustAnchor.Verify
LogTrustAnchor(const net::HashValueVector & spki_hashes)152 void LogTrustAnchor(const net::HashValueVector& spki_hashes) {
153   // Don't record metrics if there are no hashes; this is true if the HTTP
154   // load did not come from an active network connection, such as the disk
155   // cache or a synthesized response.
156   if (spki_hashes.empty())
157     return;
158 
159   int32_t id = 0;
160   for (const auto& hash : spki_hashes) {
161     id = net::GetNetTrustAnchorHistogramIdForSPKI(hash);
162     if (id != 0)
163       break;
164   }
165   base::UmaHistogramSparse("Net.Certificate.TrustAnchor.Request", id);
166 }
167 
CreateCookieOptions(net::CookieOptions::SameSiteCookieContext same_site_context)168 net::CookieOptions CreateCookieOptions(
169     net::CookieOptions::SameSiteCookieContext same_site_context) {
170   net::CookieOptions options;
171   options.set_return_excluded_cookies();
172   options.set_include_httponly();
173   options.set_same_site_cookie_context(same_site_context);
174   return options;
175 }
176 
IsTLS13OverTCP(const net::HttpResponseInfo & response_info)177 bool IsTLS13OverTCP(const net::HttpResponseInfo& response_info) {
178   // Although IETF QUIC also uses TLS 1.3, our QUIC connections report
179   // SSL_CONNECTION_VERSION_QUIC.
180   return net::SSLConnectionStatusToVersion(
181              response_info.ssl_info.connection_status) ==
182          net::SSL_CONNECTION_VERSION_TLS1_3;
183 }
184 
UpgradeSchemeToCryptographic(const GURL & insecure_url)185 GURL UpgradeSchemeToCryptographic(const GURL& insecure_url) {
186   DCHECK(!insecure_url.SchemeIsCryptographic());
187   DCHECK(insecure_url.SchemeIs(url::kHttpScheme) ||
188          insecure_url.SchemeIs(url::kWsScheme));
189 
190   GURL::Replacements replacements;
191   replacements.SetSchemeStr(insecure_url.SchemeIs(url::kHttpScheme)
192                                 ? url::kHttpsScheme
193                                 : url::kWssScheme);
194 
195   GURL secure_url = insecure_url.ReplaceComponents(replacements);
196   DCHECK(secure_url.SchemeIsCryptographic());
197 
198   return secure_url;
199 }
200 
201 // These values are persisted to logs. Entries should not be renumbered and
202 // numeric values should never be reused.
203 enum class ContentEncodingType {
204   kUnknown = 0,
205   kBrotli = 1,
206   kGZip = 2,
207   kDeflate = 3,
208   kZstd = 4,
209   kMaxValue = kZstd,
210 };
211 
IsSameSiteIgnoringWebSocketProtocol(const net::SchemefulSite & initiator,const GURL & request_url)212 bool IsSameSiteIgnoringWebSocketProtocol(const net::SchemefulSite& initiator,
213                                          const GURL& request_url) {
214   net::SchemefulSite request_site = net::SchemefulSite(
215       request_url.SchemeIsHTTPOrHTTPS()
216           ? request_url
217           : net::ChangeWebSocketSchemeToHttpScheme(request_url));
218   return initiator == request_site;
219 }
220 
221 // These values are persisted to logs. Entries should not be renumbered and
222 // numeric values should never be reused.
223 enum class HttpRequestStsState {
224   kUnknown = 0,
225   kUnprotectedHttps = 1,
226   kProtectedHttps = 2,
227   kUnprotectedHttp = 3,
228   kProtectedHttp = 4,
229   kMaxValue = kProtectedHttp,
230 };
231 
RecordSTSHistogram(bool sts_enabled,bool is_secure,int load_flags)232 void RecordSTSHistogram(bool sts_enabled, bool is_secure, int load_flags) {
233   // Embrace the layering violation and only record the histogram for main frame
234   // navigations. It's possible to record this outside of net/, but the code is
235   // a lot more complicated, and while this flag is deprecated, there are no
236   // current plans to remove it. See crbug.com/516499 .
237   if (!(load_flags & net::LOAD_MAIN_FRAME_DEPRECATED)) {
238     return;
239   }
240   HttpRequestStsState sts_state = HttpRequestStsState::kUnknown;
241   if (is_secure) {
242     sts_state = (sts_enabled ? HttpRequestStsState::kProtectedHttps
243                              : HttpRequestStsState::kUnprotectedHttps);
244   } else {
245     sts_state = (sts_enabled ? HttpRequestStsState::kProtectedHttp
246                              : HttpRequestStsState::kUnprotectedHttp);
247   }
248   UMA_HISTOGRAM_ENUMERATION("Net.HttpRequestStsState", sts_state);
249 }
250 
251 }  // namespace
252 
253 namespace net {
254 
Create(URLRequest * request)255 std::unique_ptr<URLRequestJob> URLRequestHttpJob::Create(URLRequest* request) {
256   const GURL& url = request->url();
257 
258   // URLRequestContext must have been initialized.
259   DCHECK(request->context()->http_transaction_factory());
260   DCHECK(url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS());
261 
262   TransportSecurityState* hsts = request->context()->transport_security_state();
263   bool should_upgrade_to_ssl =
264       hsts && hsts->ShouldUpgradeToSSL(url.host(), request->net_log());
265 
266   // Check for reasons not to return a URLRequestHttpJob. These don't apply to
267   // https and wss requests.
268   if (!url.SchemeIsCryptographic()) {
269     // If the request explicitly has been marked to bypass HSTS, ensure that
270     // the request is in no-credential mode so that the http site can't read
271     // or set cookies which are shared across http/https, then skip the
272     // upgrade.
273     if (((request->load_flags() & net::LOAD_SHOULD_BYPASS_HSTS) ==
274          net::LOAD_SHOULD_BYPASS_HSTS)) {
275       CHECK(request->allow_credentials() == false);
276     } else {
277       // Check for HSTS upgrade.
278       if (should_upgrade_to_ssl) {
279         RecordSTSHistogram(/*sts_enabled=*/true, /*is_secure=*/false,
280                            request->load_flags());
281         return std::make_unique<URLRequestRedirectJob>(
282             request, UpgradeSchemeToCryptographic(url),
283             // Use status code 307 to preserve the method, so POST requests
284             // work.
285             RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT,
286             "HSTS");
287       }
288     }
289 
290 #if BUILDFLAG(IS_ANDROID)
291     // Check whether the app allows cleartext traffic to this host, and return
292     // ERR_CLEARTEXT_NOT_PERMITTED if not.
293     if (request->context()->check_cleartext_permitted() &&
294         !android::IsCleartextPermitted(url.host_piece())) {
295       RecordSTSHistogram(/*sts_enabled=*/false, /*is_secure=*/false,
296                          request->load_flags());
297       return std::make_unique<URLRequestErrorJob>(request,
298                                                   ERR_CLEARTEXT_NOT_PERMITTED);
299     }
300 #endif
301   }
302 
303   RecordSTSHistogram(should_upgrade_to_ssl, url.SchemeIsCryptographic(),
304                      request->load_flags());
305   return base::WrapUnique<URLRequestJob>(new URLRequestHttpJob(
306       request, request->context()->http_user_agent_settings()));
307 }
308 
URLRequestHttpJob(URLRequest * request,const HttpUserAgentSettings * http_user_agent_settings)309 URLRequestHttpJob::URLRequestHttpJob(
310     URLRequest* request,
311     const HttpUserAgentSettings* http_user_agent_settings)
312     : URLRequestJob(request),
313       http_user_agent_settings_(http_user_agent_settings) {
314   URLRequestThrottlerManager* manager = request->context()->throttler_manager();
315   if (manager)
316     throttling_entry_ = manager->RegisterRequestUrl(request->url());
317 
318   ResetTimer();
319 }
320 
~URLRequestHttpJob()321 URLRequestHttpJob::~URLRequestHttpJob() {
322   CHECK(!awaiting_callback_);
323 
324   DoneWithRequest(ABORTED);
325 }
326 
SetPriority(RequestPriority priority)327 void URLRequestHttpJob::SetPriority(RequestPriority priority) {
328   priority_ = priority;
329   if (transaction_)
330     transaction_->SetPriority(priority_);
331 }
332 
Start()333 void URLRequestHttpJob::Start() {
334   DCHECK(!transaction_.get());
335 
336   request_info_.url = request_->url();
337   request_info_.method = request_->method();
338 
339   request_info_.network_isolation_key =
340       request_->isolation_info().network_isolation_key();
341   request_info_.network_anonymization_key =
342       request_->isolation_info().network_anonymization_key();
343   request_info_.possibly_top_frame_origin =
344       request_->isolation_info().top_frame_origin();
345   request_info_.frame_origin = request_->isolation_info().frame_origin();
346   request_info_.is_subframe_document_resource =
347       request_->isolation_info().request_type() ==
348       net::IsolationInfo::RequestType::kSubFrame;
349   request_info_.load_flags = request_->load_flags();
350   request_info_.priority_incremental = request_->priority_incremental();
351   request_info_.secure_dns_policy = request_->secure_dns_policy();
352   request_info_.traffic_annotation =
353       net::MutableNetworkTrafficAnnotationTag(request_->traffic_annotation());
354   request_info_.socket_tag = request_->socket_tag();
355   request_info_.idempotency = request_->GetIdempotency();
356 #if BUILDFLAG(ENABLE_REPORTING)
357   request_info_.reporting_upload_depth = request_->reporting_upload_depth();
358 #endif
359 
360   // Add/remove the Storage Access override enum based on whether the request's
361   // url and initiator are same-site, to prevent cross-site sibling iframes
362   // benefit from each other's storage access API grants.
363   request()->cookie_setting_overrides().PutOrRemove(
364       net::CookieSettingOverride::kStorageAccessGrantEligible,
365       request()->has_storage_access() && request_initiator_site().has_value() &&
366           IsSameSiteIgnoringWebSocketProtocol(request_initiator_site().value(),
367                                               request()->url()));
368 
369   UMA_HISTOGRAM_BOOLEAN("Net.HttpJob.CanIncludeCookies",
370                         ShouldAddCookieHeader());
371 
372   CookieStore* cookie_store = request()->context()->cookie_store();
373   const CookieAccessDelegate* delegate =
374       cookie_store ? cookie_store->cookie_access_delegate() : nullptr;
375 
376   request_->net_log().BeginEvent(NetLogEventType::FIRST_PARTY_SETS_METADATA);
377 
378   absl::optional<
379       std::pair<FirstPartySetMetadata, FirstPartySetsCacheFilter::MatchInfo>>
380       maybe_metadata = cookie_util::ComputeFirstPartySetMetadataMaybeAsync(
381           SchemefulSite(request()->url()), request()->isolation_info(),
382           delegate,
383           base::BindOnce(&URLRequestHttpJob::OnGotFirstPartySetMetadata,
384                          weak_factory_.GetWeakPtr()));
385 
386   if (maybe_metadata.has_value()) {
387     auto [metadata, match_info] = std::move(maybe_metadata).value();
388     OnGotFirstPartySetMetadata(std::move(metadata), std::move(match_info));
389   }
390 }
391 
OnGotFirstPartySetMetadata(FirstPartySetMetadata first_party_set_metadata,FirstPartySetsCacheFilter::MatchInfo match_info)392 void URLRequestHttpJob::OnGotFirstPartySetMetadata(
393     FirstPartySetMetadata first_party_set_metadata,
394     FirstPartySetsCacheFilter::MatchInfo match_info) {
395   first_party_set_metadata_ = std::move(first_party_set_metadata);
396   request_info_.fps_cache_filter = match_info.clear_at_run_id;
397   request_info_.browser_run_id = match_info.browser_run_id;
398 
399   request_->net_log().EndEvent(
400       NetLogEventType::FIRST_PARTY_SETS_METADATA, [&]() {
401         return FirstPartySetMetadataNetLogParams(
402             first_party_set_metadata_,
403             base::OptionalToPtr(request_info_.fps_cache_filter));
404       });
405 
406   // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
407   // going to send previously saved cookies.
408   request_info_.privacy_mode = DeterminePrivacyMode();
409   request()->net_log().AddEventWithStringParams(
410       NetLogEventType::COMPUTED_PRIVACY_MODE, "privacy_mode",
411       PrivacyModeToDebugString(request_info_.privacy_mode));
412 
413   // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins
414   // from overriding headers that are controlled using other means. Otherwise a
415   // plugin could set a referrer although sending the referrer is inhibited.
416   request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
417 
418   // URLRequest::SetReferrer ensures that we do not send username and password
419   // fields in the referrer.
420   GURL referrer(request_->referrer());
421 
422   // Our consumer should have made sure that this is a safe referrer (e.g. via
423   // URLRequestJob::ComputeReferrerForPolicy).
424   if (referrer.is_valid()) {
425     std::string referer_value = referrer.spec();
426     request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
427                                           referer_value);
428   }
429 
430   request_info_.extra_headers.SetHeaderIfMissing(
431       HttpRequestHeaders::kUserAgent,
432       http_user_agent_settings_ ?
433           http_user_agent_settings_->GetUserAgent() : std::string());
434 
435   AddExtraHeaders();
436 
437   if (ShouldAddCookieHeader()) {
438     AddCookieHeaderAndStart();
439   } else {
440     StartTransaction();
441   }
442 }
443 
Kill()444 void URLRequestHttpJob::Kill() {
445   weak_factory_.InvalidateWeakPtrs();
446   if (transaction_)
447     DestroyTransaction();
448   URLRequestJob::Kill();
449 }
450 
GetConnectionAttempts() const451 ConnectionAttempts URLRequestHttpJob::GetConnectionAttempts() const {
452   if (transaction_)
453     return transaction_->GetConnectionAttempts();
454   return {};
455 }
456 
CloseConnectionOnDestruction()457 void URLRequestHttpJob::CloseConnectionOnDestruction() {
458   DCHECK(transaction_);
459   transaction_->CloseConnectionOnDestruction();
460 }
461 
NotifyConnectedCallback(const TransportInfo & info,CompletionOnceCallback callback)462 int URLRequestHttpJob::NotifyConnectedCallback(
463     const TransportInfo& info,
464     CompletionOnceCallback callback) {
465   return URLRequestJob::NotifyConnected(info, std::move(callback));
466 }
467 
DeterminePrivacyMode() const468 PrivacyMode URLRequestHttpJob::DeterminePrivacyMode() const {
469   if (!request()->allow_credentials()) {
470     // |allow_credentials_| implies LOAD_DO_NOT_SAVE_COOKIES.
471     DCHECK(request_->load_flags() & LOAD_DO_NOT_SAVE_COOKIES);
472 
473     // TODO(https://crbug.com/775438): Client certs should always be
474     // affirmatively omitted for these requests.
475     return request()->send_client_certs()
476                ? PRIVACY_MODE_ENABLED
477                : PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS;
478   }
479 
480   // Otherwise, check with the delegate if present, or base it off of
481   // |URLRequest::DefaultCanUseCookies()| if not.
482   // TODO(mmenke): Looks like |URLRequest::DefaultCanUseCookies()| is not too
483   // useful, with the network service - remove it.
484   NetworkDelegate::PrivacySetting privacy_setting =
485       URLRequest::DefaultCanUseCookies()
486           ? NetworkDelegate::PrivacySetting::kStateAllowed
487           : NetworkDelegate::PrivacySetting::kStateDisallowed;
488   if (request_->network_delegate()) {
489     privacy_setting =
490         request()->network_delegate()->ForcePrivacyMode(*request());
491   }
492   switch (privacy_setting) {
493     case NetworkDelegate::PrivacySetting::kStateAllowed:
494       return PRIVACY_MODE_DISABLED;
495     case NetworkDelegate::PrivacySetting::kPartitionedStateAllowedOnly:
496       return PRIVACY_MODE_ENABLED_PARTITIONED_STATE_ALLOWED;
497     case NetworkDelegate::PrivacySetting::kStateDisallowed:
498       return PRIVACY_MODE_ENABLED;
499   }
500   NOTREACHED();
501   return PRIVACY_MODE_ENABLED;
502 }
503 
NotifyHeadersComplete()504 void URLRequestHttpJob::NotifyHeadersComplete() {
505   DCHECK(!response_info_);
506   DCHECK_EQ(0, num_cookie_lines_left_);
507   DCHECK(request_->maybe_stored_cookies().empty());
508 
509   if (override_response_info_) {
510     DCHECK(!transaction_);
511     response_info_ = override_response_info_.get();
512   } else {
513     response_info_ = transaction_->GetResponseInfo();
514   }
515 
516   if (!response_info_->was_cached && throttling_entry_.get())
517     throttling_entry_->UpdateWithResponse(GetResponseCode());
518 
519   ProcessStrictTransportSecurityHeader();
520 
521   // Clear |set_cookie_access_result_list_| after any processing in case
522   // SaveCookiesAndNotifyHeadersComplete is called again.
523   request_->set_maybe_stored_cookies(std::move(set_cookie_access_result_list_));
524 
525   // The HTTP transaction may be restarted several times for the purposes
526   // of sending authorization information. Each time it restarts, we get
527   // notified of the headers completion so that we can update the cookie store.
528   if (transaction_ && transaction_->IsReadyToRestartForAuth()) {
529     // TODO(battre): This breaks the webrequest API for
530     // URLRequestTestHTTP.BasicAuthWithCookies
531     // where OnBeforeStartTransaction -> OnStartTransaction ->
532     // OnBeforeStartTransaction occurs.
533     RestartTransactionWithAuth(AuthCredentials());
534     return;
535   }
536 
537   URLRequestJob::NotifyHeadersComplete();
538 }
539 
DestroyTransaction()540 void URLRequestHttpJob::DestroyTransaction() {
541   DCHECK(transaction_.get());
542 
543   DoneWithRequest(ABORTED);
544 
545   total_received_bytes_from_previous_transactions_ +=
546       transaction_->GetTotalReceivedBytes();
547   total_sent_bytes_from_previous_transactions_ +=
548       transaction_->GetTotalSentBytes();
549   response_info_ = nullptr;
550   transaction_.reset();
551   override_response_headers_ = nullptr;
552   receive_headers_end_ = base::TimeTicks();
553 }
554 
StartTransaction()555 void URLRequestHttpJob::StartTransaction() {
556   DCHECK(!override_response_info_);
557 
558   NetworkDelegate* network_delegate = request()->network_delegate();
559   if (network_delegate) {
560     OnCallToDelegate(
561         NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
562     int rv = network_delegate->NotifyBeforeStartTransaction(
563         request_, request_info_.extra_headers,
564         base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
565                        weak_factory_.GetWeakPtr()));
566     // If an extension blocks the request, we rely on the callback to
567     // MaybeStartTransactionInternal().
568     if (rv == ERR_IO_PENDING)
569       return;
570     MaybeStartTransactionInternal(rv);
571     return;
572   }
573   StartTransactionInternal();
574 }
575 
NotifyBeforeStartTransactionCallback(int result,const absl::optional<HttpRequestHeaders> & headers)576 void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(
577     int result,
578     const absl::optional<HttpRequestHeaders>& headers) {
579   // The request should not have been cancelled or have already completed.
580   DCHECK(!is_done());
581 
582   if (headers)
583     request_info_.extra_headers = headers.value();
584   MaybeStartTransactionInternal(result);
585 }
586 
MaybeStartTransactionInternal(int result)587 void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
588   OnCallToDelegateComplete();
589   if (result == OK) {
590     StartTransactionInternal();
591   } else {
592     request_->net_log().AddEventWithStringParams(NetLogEventType::CANCELLED,
593                                                  "source", "delegate");
594     // Don't call back synchronously to the delegate.
595     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
596         FROM_HERE, base::BindOnce(&URLRequestHttpJob::NotifyStartError,
597                                   weak_factory_.GetWeakPtr(), result));
598   }
599 }
600 
StartTransactionInternal()601 void URLRequestHttpJob::StartTransactionInternal() {
602   DCHECK(!override_response_headers_);
603 
604   // NOTE: This method assumes that request_info_ is already setup properly.
605 
606   // If we already have a transaction, then we should restart the transaction
607   // with auth provided by auth_credentials_.
608 
609   int rv;
610 
611   // Notify NetworkQualityEstimator.
612   NetworkQualityEstimator* network_quality_estimator =
613       request()->context()->network_quality_estimator();
614   if (network_quality_estimator)
615     network_quality_estimator->NotifyStartTransaction(*request_);
616 
617   if (transaction_.get()) {
618     rv = transaction_->RestartWithAuth(
619         auth_credentials_, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
620                                           base::Unretained(this)));
621     auth_credentials_ = AuthCredentials();
622   } else {
623     DCHECK(request_->context()->http_transaction_factory());
624 
625     rv = request_->context()->http_transaction_factory()->CreateTransaction(
626         priority_, &transaction_);
627 
628     if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
629       base::SupportsUserData::Data* data =
630           request_->GetUserData(kWebSocketHandshakeUserDataKey);
631       if (data) {
632         transaction_->SetWebSocketHandshakeStreamCreateHelper(
633             static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
634       } else {
635         rv = ERR_DISALLOWED_URL_SCHEME;
636       }
637     }
638 
639     if (rv == OK && request_info_.method == "CONNECT") {
640       // CONNECT has different kinds of targets than other methods (RFC 9110,
641       // section 9.3.6), which are incompatible with URLRequest.
642       rv = ERR_METHOD_NOT_SUPPORTED;
643     }
644 
645     if (rv == OK) {
646       transaction_->SetConnectedCallback(base::BindRepeating(
647           &URLRequestHttpJob::NotifyConnectedCallback, base::Unretained(this)));
648       transaction_->SetRequestHeadersCallback(request_headers_callback_);
649       transaction_->SetEarlyResponseHeadersCallback(
650           early_response_headers_callback_);
651       transaction_->SetResponseHeadersCallback(response_headers_callback_);
652       if (is_shared_dictionary_read_allowed_callback_) {
653         transaction_->SetIsSharedDictionaryReadAllowedCallback(
654             is_shared_dictionary_read_allowed_callback_);
655       }
656 
657       if (!throttling_entry_.get() ||
658           !throttling_entry_->ShouldRejectRequest(*request_)) {
659         rv = transaction_->Start(
660             &request_info_,
661             base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
662                            base::Unretained(this)),
663             request_->net_log());
664         start_time_ = base::TimeTicks::Now();
665       } else {
666         // Special error code for the exponential back-off module.
667         rv = ERR_TEMPORARILY_THROTTLED;
668       }
669     }
670   }
671 
672   if (rv == ERR_IO_PENDING)
673     return;
674 
675   // The transaction started synchronously, but we need to notify the
676   // URLRequest delegate via the message loop.
677   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
678       FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
679                                 weak_factory_.GetWeakPtr(), rv));
680 }
681 
AddExtraHeaders()682 void URLRequestHttpJob::AddExtraHeaders() {
683   request_info_.extra_headers.SetAcceptEncodingIfMissing(
684       request()->url(), request()->accepted_stream_types(),
685       request()->context()->enable_brotli(),
686       request()->context()->enable_zstd());
687 
688   if (http_user_agent_settings_) {
689     // Only add default Accept-Language if the request didn't have it
690     // specified.
691     std::string accept_language =
692         http_user_agent_settings_->GetAcceptLanguage();
693     if (!accept_language.empty()) {
694       request_info_.extra_headers.SetHeaderIfMissing(
695           HttpRequestHeaders::kAcceptLanguage,
696           accept_language);
697     }
698   }
699 }
700 
AddCookieHeaderAndStart()701 void URLRequestHttpJob::AddCookieHeaderAndStart() {
702   CookieStore* cookie_store = request_->context()->cookie_store();
703   DCHECK(cookie_store);
704   DCHECK(ShouldAddCookieHeader());
705   bool force_ignore_site_for_cookies =
706       request_->force_ignore_site_for_cookies();
707   if (cookie_store->cookie_access_delegate() &&
708       cookie_store->cookie_access_delegate()->ShouldIgnoreSameSiteRestrictions(
709           request_->url(), request_->site_for_cookies())) {
710     force_ignore_site_for_cookies = true;
711   }
712   bool is_main_frame_navigation =
713       IsolationInfo::RequestType::kMainFrame ==
714           request_->isolation_info().request_type() ||
715       request_->force_main_frame_for_same_site_cookies();
716   CookieOptions::SameSiteCookieContext same_site_context =
717       net::cookie_util::ComputeSameSiteContextForRequest(
718           request_->method(), request_->url_chain(),
719           request_->site_for_cookies(), request_->initiator(),
720           is_main_frame_navigation, force_ignore_site_for_cookies);
721 
722   CookieOptions options = CreateCookieOptions(same_site_context);
723 
724   cookie_store->GetCookieListWithOptionsAsync(
725       request_->url(), options,
726       CookiePartitionKeyCollection::FromOptional(
727           request_->cookie_partition_key()),
728       base::BindOnce(&URLRequestHttpJob::SetCookieHeaderAndStart,
729                      weak_factory_.GetWeakPtr(), options));
730 }
731 
732 namespace {
733 
ShouldBlockAllCookies(const PrivacyMode & privacy_mode)734 bool ShouldBlockAllCookies(const PrivacyMode& privacy_mode) {
735   return privacy_mode == PRIVACY_MODE_ENABLED ||
736          privacy_mode == PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS;
737 }
738 
739 }  // namespace
740 
SetCookieHeaderAndStart(const CookieOptions & options,const CookieAccessResultList & cookies_with_access_result_list,const CookieAccessResultList & excluded_list)741 void URLRequestHttpJob::SetCookieHeaderAndStart(
742     const CookieOptions& options,
743     const CookieAccessResultList& cookies_with_access_result_list,
744     const CookieAccessResultList& excluded_list) {
745   DCHECK(request_->maybe_sent_cookies().empty());
746 
747   CookieAccessResultList maybe_included_cookies =
748       cookies_with_access_result_list;
749   CookieAccessResultList excluded_cookies = excluded_list;
750 
751   if (ShouldBlockAllCookies(request_info_.privacy_mode)) {
752     // If cookies are blocked (without our needing to consult the delegate),
753     // we move them to `excluded_cookies` and ensure that they have the
754     // correct exclusion reason.
755     excluded_cookies.insert(
756         excluded_cookies.end(),
757         std::make_move_iterator(maybe_included_cookies.begin()),
758         std::make_move_iterator(maybe_included_cookies.end()));
759     maybe_included_cookies.clear();
760     for (auto& cookie : excluded_cookies) {
761       cookie.access_result.status.AddExclusionReason(
762           CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
763     }
764   } else {
765     // Consult the delegate to ensure that they have the correct exclusion
766     // reason.
767     AnnotateAndMoveUserBlockedCookies(maybe_included_cookies, excluded_cookies);
768   }
769 
770   if (!maybe_included_cookies.empty()) {
771     std::string cookie_line =
772         CanonicalCookie::BuildCookieLine(maybe_included_cookies);
773     request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
774                                           cookie_line);
775 
776     size_t n_partitioned_cookies = 0;
777     bool may_set_sec_cookie_deprecation_header =
778         !request_->context()->cookie_deprecation_label().value_or("").empty();
779 
780     // TODO(crbug.com/1031664): Reduce the number of times the cookie list
781     // is iterated over. Get metrics for every cookie which is included.
782     for (const auto& c : maybe_included_cookies) {
783       bool request_is_secure = request_->url().SchemeIsCryptographic();
784       net::CookieSourceScheme cookie_scheme = c.cookie.SourceScheme();
785       CookieRequestScheme cookie_request_schemes;
786 
787       switch (cookie_scheme) {
788         case net::CookieSourceScheme::kSecure:
789           cookie_request_schemes =
790               request_is_secure
791                   ? CookieRequestScheme::kSecureSetSecureRequest
792                   : CookieRequestScheme::kSecureSetNonsecureRequest;
793           break;
794 
795         case net::CookieSourceScheme::kNonSecure:
796           cookie_request_schemes =
797               request_is_secure
798                   ? CookieRequestScheme::kNonsecureSetSecureRequest
799                   : CookieRequestScheme::kNonsecureSetNonsecureRequest;
800           break;
801 
802         case net::CookieSourceScheme::kUnset:
803           cookie_request_schemes = CookieRequestScheme::kUnsetCookieScheme;
804           break;
805       }
806 
807       UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSchemeRequestScheme",
808                                 cookie_request_schemes);
809       if (c.cookie.IsPartitioned()) {
810         ++n_partitioned_cookies;
811 
812         if (may_set_sec_cookie_deprecation_header &&
813             c.cookie.Name() == "receive-cookie-deprecation" &&
814             c.cookie.IsHttpOnly() && c.cookie.IsSecure()) {
815           request_info_.extra_headers.SetHeader(
816               "Sec-Cookie-Deprecation",
817               *request_->context()->cookie_deprecation_label());
818           may_set_sec_cookie_deprecation_header = false;
819         }
820       }
821     }
822 
823     if (ShouldRecordPartitionedCookieUsage()) {
824       base::UmaHistogramCounts100("Cookie.PartitionedCookiesInRequest",
825                                   n_partitioned_cookies);
826     }
827   }
828 
829   CookieAccessResultList maybe_sent_cookies = std::move(excluded_cookies);
830   maybe_sent_cookies.insert(
831       maybe_sent_cookies.end(),
832       std::make_move_iterator(maybe_included_cookies.begin()),
833       std::make_move_iterator(maybe_included_cookies.end()));
834   maybe_included_cookies.clear();
835 
836   if (request_->net_log().IsCapturing()) {
837     for (const auto& cookie_with_access_result : maybe_sent_cookies) {
838       request_->net_log().AddEvent(
839           NetLogEventType::COOKIE_INCLUSION_STATUS,
840           [&](NetLogCaptureMode capture_mode) {
841             return CookieInclusionStatusNetLogParams(
842                 "send", cookie_with_access_result.cookie.Name(),
843                 cookie_with_access_result.cookie.Domain(),
844                 cookie_with_access_result.cookie.Path(),
845                 cookie_with_access_result.access_result.status, capture_mode);
846           });
847     }
848   }
849 
850   request_->set_maybe_sent_cookies(std::move(maybe_sent_cookies));
851 
852   StartTransaction();
853 }
854 
AnnotateAndMoveUserBlockedCookies(CookieAccessResultList & maybe_included_cookies,CookieAccessResultList & excluded_cookies) const855 void URLRequestHttpJob::AnnotateAndMoveUserBlockedCookies(
856     CookieAccessResultList& maybe_included_cookies,
857     CookieAccessResultList& excluded_cookies) const {
858   DCHECK(!ShouldBlockAllCookies(request_info_.privacy_mode))
859       << request_info_.privacy_mode;
860 
861   bool can_get_cookies = URLRequest::DefaultCanUseCookies();
862   if (request()->network_delegate()) {
863     can_get_cookies =
864         request()->network_delegate()->AnnotateAndMoveUserBlockedCookies(
865             *request(), first_party_set_metadata_, maybe_included_cookies,
866             excluded_cookies);
867   }
868 
869   if (!can_get_cookies) {
870     request()->net_log().AddEvent(
871         NetLogEventType::COOKIE_GET_BLOCKED_BY_NETWORK_DELEGATE);
872   }
873 }
874 
SaveCookiesAndNotifyHeadersComplete(int result)875 void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
876   DCHECK(set_cookie_access_result_list_.empty());
877   // TODO(crbug.com/1186863): Turn this CHECK into DCHECK once the investigation
878   // is done.
879   CHECK_EQ(0, num_cookie_lines_left_);
880 
881   // End of the call started in OnStartCompleted.
882   OnCallToDelegateComplete();
883 
884   if (result != OK) {
885     request_->net_log().AddEventWithStringParams(NetLogEventType::CANCELLED,
886                                                  "source", "delegate");
887     NotifyStartError(result);
888     return;
889   }
890 
891   CookieStore* cookie_store = request_->context()->cookie_store();
892 
893   if ((request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) || !cookie_store) {
894     NotifyHeadersComplete();
895     return;
896   }
897 
898   HttpResponseHeaders* headers = GetResponseHeaders();
899 
900   // If we're clearing the cookies as part of a clear-site-data header we must
901   // not also write new ones in the same response.
902   bool clear_site_data_prevents_cookies_from_being_stored = false;
903   std::string clear_site_data_header;
904   headers->GetNormalizedHeader(kClearSiteDataHeader, &clear_site_data_header);
905   std::vector<std::string> clear_site_data_types =
906       ClearSiteDataHeaderContents(clear_site_data_header);
907   std::set<std::string> clear_site_data_set(clear_site_data_types.begin(),
908                                             clear_site_data_types.end());
909   if (clear_site_data_set.find(kDatatypeCookies) != clear_site_data_set.end() ||
910       clear_site_data_set.find(kDatatypeWildcard) !=
911           clear_site_data_set.end()) {
912     clear_site_data_prevents_cookies_from_being_stored = true;
913   }
914 
915   base::Time response_date;
916   absl::optional<base::Time> server_time = absl::nullopt;
917   if (GetResponseHeaders()->GetDateValue(&response_date))
918     server_time = absl::make_optional(response_date);
919 
920   bool force_ignore_site_for_cookies =
921       request_->force_ignore_site_for_cookies();
922   if (cookie_store->cookie_access_delegate() &&
923       cookie_store->cookie_access_delegate()->ShouldIgnoreSameSiteRestrictions(
924           request_->url(), request_->site_for_cookies())) {
925     force_ignore_site_for_cookies = true;
926   }
927   bool is_main_frame_navigation =
928       IsolationInfo::RequestType::kMainFrame ==
929           request_->isolation_info().request_type() ||
930       request_->force_main_frame_for_same_site_cookies();
931   CookieOptions::SameSiteCookieContext same_site_context =
932       net::cookie_util::ComputeSameSiteContextForResponse(
933           request_->url_chain(), request_->site_for_cookies(),
934           request_->initiator(), is_main_frame_navigation,
935           force_ignore_site_for_cookies);
936 
937   CookieOptions options = CreateCookieOptions(same_site_context);
938 
939   // Set all cookies, without waiting for them to be set. Any subsequent
940   // read will see the combined result of all cookie operation.
941   const base::StringPiece name("Set-Cookie");
942   std::string cookie_string;
943   size_t iter = 0;
944 
945   // NotifyHeadersComplete needs to be called once and only once after the
946   // list has been fully processed, and it can either be called in the
947   // callback or after the loop is called, depending on how the last element
948   // was handled. |num_cookie_lines_left_| keeps track of how many async
949   // callbacks are currently out (starting from 1 to make sure the loop runs
950   // all the way through before trying to exit). If there are any callbacks
951   // still waiting when the loop ends, then NotifyHeadersComplete will be
952   // called when it reaches 0 in the callback itself.
953   num_cookie_lines_left_ = 1;
954   while (headers->EnumerateHeader(&iter, name, &cookie_string)) {
955     CookieInclusionStatus returned_status;
956 
957     num_cookie_lines_left_++;
958 
959     // For the block_truncated parameter, the value shouldn't matter here
960     // because HTTP requests containing NULLs causes an error before this code
961     // can be reached and unpaired carriage returns and line feed characters
962     // cause truncation during HTTP header processing before reaching this
963     // point, so DCHECK this assumption and just pass true for this parameter.
964     DCHECK(cookie_string.find('\0') == std::string::npos);
965     DCHECK(cookie_string.find('\r') == std::string::npos);
966     DCHECK(cookie_string.find('\n') == std::string::npos);
967     std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
968         request_->url(), cookie_string, base::Time::Now(), server_time,
969         request_->cookie_partition_key(), /*block_truncated=*/true,
970         &returned_status);
971 
972     absl::optional<CanonicalCookie> cookie_to_return = absl::nullopt;
973     if (returned_status.IsInclude()) {
974       DCHECK(cookie);
975       // Make a copy of the cookie if we successfully made one.
976       cookie_to_return = *cookie;
977     }
978 
979     // Check cookie accessibility with cookie_settings.
980     if (cookie && !CanSetCookie(*cookie, &options, first_party_set_metadata_,
981                                 &returned_status)) {
982       // Cookie allowed by cookie_settings checks could be blocked explicitly,
983       // e.g. via Android Webview APIs, we need to manually add exclusion reason
984       // in this case.
985       if (returned_status.IsInclude()) {
986         returned_status.AddExclusionReason(
987             net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
988       }
989     }
990     if (clear_site_data_prevents_cookies_from_being_stored) {
991       returned_status.AddExclusionReason(
992           CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
993     }
994     if (!returned_status.IsInclude()) {
995       OnSetCookieResult(options, cookie_to_return, std::move(cookie_string),
996                         CookieAccessResult(returned_status));
997       continue;
998     }
999     CookieAccessResult cookie_access_result(returned_status);
1000     cookie_store->SetCanonicalCookieAsync(
1001         std::move(cookie), request_->url(), options,
1002         base::BindOnce(&URLRequestHttpJob::OnSetCookieResult,
1003                        weak_factory_.GetWeakPtr(), options, cookie_to_return,
1004                        cookie_string),
1005         std::move(cookie_access_result));
1006   }
1007   // Removing the 1 that |num_cookie_lines_left| started with, signifing that
1008   // loop has been exited.
1009   num_cookie_lines_left_--;
1010 
1011   if (num_cookie_lines_left_ == 0)
1012     NotifyHeadersComplete();
1013 }
1014 
OnSetCookieResult(const CookieOptions & options,absl::optional<CanonicalCookie> cookie,std::string cookie_string,CookieAccessResult access_result)1015 void URLRequestHttpJob::OnSetCookieResult(
1016     const CookieOptions& options,
1017     absl::optional<CanonicalCookie> cookie,
1018     std::string cookie_string,
1019     CookieAccessResult access_result) {
1020   if (request_->net_log().IsCapturing()) {
1021     request_->net_log().AddEvent(NetLogEventType::COOKIE_INCLUSION_STATUS,
1022                                  [&](NetLogCaptureMode capture_mode) {
1023                                    return CookieInclusionStatusNetLogParams(
1024                                        "store",
1025                                        cookie ? cookie.value().Name() : "",
1026                                        cookie ? cookie.value().Domain() : "",
1027                                        cookie ? cookie.value().Path() : "",
1028                                        access_result.status, capture_mode);
1029                                  });
1030   }
1031 
1032   set_cookie_access_result_list_.emplace_back(
1033       std::move(cookie), std::move(cookie_string), access_result);
1034 
1035   num_cookie_lines_left_--;
1036 
1037   // If all the cookie lines have been handled, |set_cookie_access_result_list_|
1038   // now reflects the result of all Set-Cookie lines, and the request can be
1039   // continued.
1040   if (num_cookie_lines_left_ == 0)
1041     NotifyHeadersComplete();
1042 }
1043 
ProcessStrictTransportSecurityHeader()1044 void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
1045   DCHECK(response_info_);
1046   TransportSecurityState* security_state =
1047       request_->context()->transport_security_state();
1048   const SSLInfo& ssl_info = response_info_->ssl_info;
1049 
1050   // Only accept HSTS headers on HTTPS connections that have no
1051   // certificate errors.
1052   if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
1053       !security_state) {
1054     return;
1055   }
1056 
1057   // Don't accept HSTS headers when the hostname is an IP address.
1058   if (request_info_.url.HostIsIPAddress())
1059     return;
1060 
1061   // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec:
1062   //
1063   //   If a UA receives more than one STS header field in a HTTP response
1064   //   message over secure transport, then the UA MUST process only the
1065   //   first such header field.
1066   HttpResponseHeaders* headers = GetResponseHeaders();
1067   std::string value;
1068   if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
1069     security_state->AddHSTSHeader(request_info_.url.host(), value);
1070 }
1071 
OnStartCompleted(int result)1072 void URLRequestHttpJob::OnStartCompleted(int result) {
1073   TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnStartCompleted");
1074   RecordTimer();
1075 
1076   // If the job is done (due to cancellation), can just ignore this
1077   // notification.
1078   if (done_)
1079     return;
1080 
1081   receive_headers_end_ = base::TimeTicks::Now();
1082 
1083   const URLRequestContext* context = request_->context();
1084 
1085   if (transaction_ && transaction_->GetResponseInfo()) {
1086     const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
1087     if (!IsCertificateError(result)) {
1088       LogTrustAnchor(ssl_info.public_key_hashes);
1089     }
1090   }
1091 
1092   if (transaction_ && transaction_->GetResponseInfo()) {
1093     SetProxyChain(transaction_->GetResponseInfo()->proxy_chain);
1094   }
1095 
1096   if (result == OK) {
1097     scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
1098 
1099     NetworkDelegate* network_delegate = request()->network_delegate();
1100     if (network_delegate) {
1101       // Note that |this| may not be deleted until
1102       // |URLRequestHttpJob::OnHeadersReceivedCallback()| or
1103       // |NetworkDelegate::URLRequestDestroyed()| has been called.
1104       OnCallToDelegate(NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED);
1105       preserve_fragment_on_redirect_url_ = absl::nullopt;
1106       IPEndPoint endpoint;
1107       if (transaction_)
1108         transaction_->GetRemoteEndpoint(&endpoint);
1109       // The NetworkDelegate must watch for OnRequestDestroyed and not modify
1110       // any of the arguments after it's called.
1111       // TODO(mattm): change the API to remove the out-params and take the
1112       // results as params of the callback.
1113       int error = network_delegate->NotifyHeadersReceived(
1114           request_,
1115           base::BindOnce(&URLRequestHttpJob::OnHeadersReceivedCallback,
1116                          weak_factory_.GetWeakPtr()),
1117           headers.get(), &override_response_headers_, endpoint,
1118           &preserve_fragment_on_redirect_url_);
1119       if (error != OK) {
1120         if (error == ERR_IO_PENDING) {
1121           awaiting_callback_ = true;
1122         } else {
1123           request_->net_log().AddEventWithStringParams(
1124               NetLogEventType::CANCELLED, "source", "delegate");
1125           OnCallToDelegateComplete();
1126           NotifyStartError(error);
1127         }
1128         return;
1129       }
1130     }
1131 
1132     SaveCookiesAndNotifyHeadersComplete(OK);
1133   } else if (IsCertificateError(result)) {
1134     // We encountered an SSL certificate error.
1135     // Maybe overridable, maybe not. Ask the delegate to decide.
1136     TransportSecurityState* state = context->transport_security_state();
1137     NotifySSLCertificateError(
1138         result, transaction_->GetResponseInfo()->ssl_info,
1139         state->ShouldSSLErrorsBeFatal(request_info_.url.host()) &&
1140             result != ERR_CERT_KNOWN_INTERCEPTION_BLOCKED);
1141   } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
1142     NotifyCertificateRequested(
1143         transaction_->GetResponseInfo()->cert_request_info.get());
1144   } else if (result == ERR_DNS_NAME_HTTPS_ONLY) {
1145     // If DNS indicated the name is HTTPS-only, synthesize a redirect to either
1146     // HTTPS or WSS.
1147     DCHECK(!request_->url().SchemeIsCryptographic());
1148 
1149     base::Time request_time =
1150         transaction_ && transaction_->GetResponseInfo()
1151             ? transaction_->GetResponseInfo()->request_time
1152             : base::Time::Now();
1153     DestroyTransaction();
1154     override_response_info_ = std::make_unique<HttpResponseInfo>();
1155     override_response_info_->request_time = request_time;
1156 
1157     override_response_info_->headers = RedirectUtil::SynthesizeRedirectHeaders(
1158         UpgradeSchemeToCryptographic(request_->url()),
1159         RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT, "DNS",
1160         request_->extra_request_headers());
1161     NetLogResponseHeaders(
1162         request_->net_log(),
1163         NetLogEventType::URL_REQUEST_FAKE_RESPONSE_HEADERS_CREATED,
1164         override_response_info_->headers.get());
1165 
1166     NotifyHeadersComplete();
1167   } else {
1168     // Even on an error, there may be useful information in the response
1169     // info (e.g. whether there's a cached copy).
1170     if (transaction_.get())
1171       response_info_ = transaction_->GetResponseInfo();
1172     NotifyStartError(result);
1173   }
1174 }
1175 
OnHeadersReceivedCallback(int result)1176 void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
1177   // The request should not have been cancelled or have already completed.
1178   DCHECK(!is_done());
1179 
1180   awaiting_callback_ = false;
1181 
1182   SaveCookiesAndNotifyHeadersComplete(result);
1183 }
1184 
OnReadCompleted(int result)1185 void URLRequestHttpJob::OnReadCompleted(int result) {
1186   TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnReadCompleted");
1187   read_in_progress_ = false;
1188 
1189   DCHECK_NE(ERR_IO_PENDING, result);
1190 
1191   if (ShouldFixMismatchedContentLength(result))
1192     result = OK;
1193 
1194   // EOF or error, done with this job.
1195   if (result <= 0)
1196     DoneWithRequest(FINISHED);
1197 
1198   ReadRawDataComplete(result);
1199 }
1200 
RestartTransactionWithAuth(const AuthCredentials & credentials)1201 void URLRequestHttpJob::RestartTransactionWithAuth(
1202     const AuthCredentials& credentials) {
1203   DCHECK(!override_response_info_);
1204 
1205   auth_credentials_ = credentials;
1206 
1207   // These will be reset in OnStartCompleted.
1208   response_info_ = nullptr;
1209   override_response_headers_ = nullptr;  // See https://crbug.com/801237.
1210   receive_headers_end_ = base::TimeTicks();
1211 
1212   ResetTimer();
1213 
1214   // Update the cookies, since the cookie store may have been updated from the
1215   // headers in the 401/407. Since cookies were already appended to
1216   // extra_headers, we need to strip them out before adding them again.
1217   request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kCookie);
1218 
1219   // TODO(https://crbug.com/968327/): This is weird, as all other clearing is at
1220   // the URLRequest layer. Should this call into URLRequest so it can share
1221   // logic at that layer with SetAuth()?
1222   request_->set_maybe_sent_cookies({});
1223   request_->set_maybe_stored_cookies({});
1224 
1225   if (ShouldAddCookieHeader()) {
1226     // Since `request_->isolation_info()` hasn't changed, we don't need to
1227     // recompute the cookie partition key.
1228     AddCookieHeaderAndStart();
1229   } else {
1230     StartTransaction();
1231   }
1232 }
1233 
SetUpload(UploadDataStream * upload)1234 void URLRequestHttpJob::SetUpload(UploadDataStream* upload) {
1235   DCHECK(!transaction_.get() && !override_response_info_)
1236       << "cannot change once started";
1237   request_info_.upload_data_stream = upload;
1238 }
1239 
SetExtraRequestHeaders(const HttpRequestHeaders & headers)1240 void URLRequestHttpJob::SetExtraRequestHeaders(
1241     const HttpRequestHeaders& headers) {
1242   DCHECK(!transaction_.get() && !override_response_info_)
1243       << "cannot change once started";
1244   request_info_.extra_headers = headers;
1245 }
1246 
GetLoadState() const1247 LoadState URLRequestHttpJob::GetLoadState() const {
1248   return transaction_.get() ?
1249       transaction_->GetLoadState() : LOAD_STATE_IDLE;
1250 }
1251 
GetMimeType(std::string * mime_type) const1252 bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
1253   DCHECK(transaction_.get() || override_response_info_);
1254 
1255   if (!response_info_)
1256     return false;
1257 
1258   HttpResponseHeaders* headers = GetResponseHeaders();
1259   if (!headers)
1260     return false;
1261   return headers->GetMimeType(mime_type);
1262 }
1263 
GetCharset(std::string * charset)1264 bool URLRequestHttpJob::GetCharset(std::string* charset) {
1265   DCHECK(transaction_.get() || override_response_info_);
1266 
1267   if (!response_info_)
1268     return false;
1269 
1270   return GetResponseHeaders()->GetCharset(charset);
1271 }
1272 
GetResponseInfo(HttpResponseInfo * info)1273 void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
1274   if (override_response_info_) {
1275     DCHECK(!transaction_.get());
1276     *info = *override_response_info_;
1277     return;
1278   }
1279 
1280   if (response_info_) {
1281     DCHECK(transaction_.get());
1282 
1283     *info = *response_info_;
1284     if (override_response_headers_.get())
1285       info->headers = override_response_headers_;
1286   }
1287 }
1288 
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const1289 void URLRequestHttpJob::GetLoadTimingInfo(
1290     LoadTimingInfo* load_timing_info) const {
1291   // If haven't made it far enough to receive any headers, don't return
1292   // anything. This makes for more consistent behavior in the case of errors.
1293   if (!transaction_ || receive_headers_end_.is_null())
1294     return;
1295   if (transaction_->GetLoadTimingInfo(load_timing_info))
1296     load_timing_info->receive_headers_end = receive_headers_end_;
1297 }
1298 
GetTransactionRemoteEndpoint(IPEndPoint * endpoint) const1299 bool URLRequestHttpJob::GetTransactionRemoteEndpoint(
1300     IPEndPoint* endpoint) const {
1301   if (!transaction_)
1302     return false;
1303 
1304   return transaction_->GetRemoteEndpoint(endpoint);
1305 }
1306 
GetResponseCode() const1307 int URLRequestHttpJob::GetResponseCode() const {
1308   DCHECK(transaction_.get());
1309 
1310   if (!response_info_)
1311     return -1;
1312 
1313   return GetResponseHeaders()->response_code();
1314 }
1315 
PopulateNetErrorDetails(NetErrorDetails * details) const1316 void URLRequestHttpJob::PopulateNetErrorDetails(
1317     NetErrorDetails* details) const {
1318   if (!transaction_)
1319     return;
1320   return transaction_->PopulateNetErrorDetails(details);
1321 }
1322 
SetUpSourceStream()1323 std::unique_ptr<SourceStream> URLRequestHttpJob::SetUpSourceStream() {
1324   DCHECK(transaction_.get());
1325   if (!response_info_)
1326     return nullptr;
1327 
1328   std::unique_ptr<SourceStream> upstream = URLRequestJob::SetUpSourceStream();
1329   HttpResponseHeaders* headers = GetResponseHeaders();
1330   std::vector<SourceStream::SourceType> types;
1331   size_t iter = 0;
1332   for (std::string type;
1333        headers->EnumerateHeader(&iter, "Content-Encoding", &type);) {
1334     SourceStream::SourceType source_type =
1335         FilterSourceStream::ParseEncodingType(type);
1336     switch (source_type) {
1337       case SourceStream::TYPE_BROTLI:
1338       case SourceStream::TYPE_DEFLATE:
1339       case SourceStream::TYPE_GZIP:
1340       case SourceStream::TYPE_ZSTD:
1341         if (request_->accepted_stream_types() &&
1342             !request_->accepted_stream_types()->contains(source_type)) {
1343           // If the source type is disabled, we treat it
1344           // in the same way as SourceStream::TYPE_UNKNOWN.
1345           return upstream;
1346         }
1347         types.push_back(source_type);
1348         break;
1349       case SourceStream::TYPE_NONE:
1350         // Identity encoding type. Pass through raw response body.
1351         return upstream;
1352       case SourceStream::TYPE_UNKNOWN:
1353         // Unknown encoding type. Pass through raw response body.
1354         // Request will not be canceled; though
1355         // it is expected that user will see malformed / garbage response.
1356         return upstream;
1357     }
1358   }
1359 
1360   ContentEncodingType content_encoding_type = ContentEncodingType::kUnknown;
1361 
1362   for (const auto& type : base::Reversed(types)) {
1363     std::unique_ptr<FilterSourceStream> downstream;
1364     switch (type) {
1365       case SourceStream::TYPE_BROTLI:
1366         downstream = CreateBrotliSourceStream(std::move(upstream));
1367         content_encoding_type = ContentEncodingType::kBrotli;
1368         break;
1369       case SourceStream::TYPE_GZIP:
1370       case SourceStream::TYPE_DEFLATE:
1371         downstream = GzipSourceStream::Create(std::move(upstream), type);
1372         content_encoding_type = type == SourceStream::TYPE_GZIP
1373                                     ? ContentEncodingType::kGZip
1374                                     : ContentEncodingType::kDeflate;
1375         break;
1376       case SourceStream::TYPE_ZSTD:
1377         downstream = CreateZstdSourceStream(std::move(upstream));
1378         content_encoding_type = ContentEncodingType::kZstd;
1379         break;
1380       case SourceStream::TYPE_NONE:
1381       case SourceStream::TYPE_UNKNOWN:
1382         NOTREACHED();
1383         return nullptr;
1384     }
1385     if (downstream == nullptr)
1386       return nullptr;
1387     upstream = std::move(downstream);
1388   }
1389 
1390   // Note: If multiple encoding types were specified, this only records the last
1391   // encoding type.
1392   UMA_HISTOGRAM_ENUMERATION("Net.ContentEncodingType", content_encoding_type);
1393 
1394   return upstream;
1395 }
1396 
CopyFragmentOnRedirect(const GURL & location) const1397 bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const {
1398   // Allow modification of reference fragments by default, unless
1399   // |preserve_fragment_on_redirect_url_| is set and equal to the redirect URL.
1400   return !preserve_fragment_on_redirect_url_.has_value() ||
1401          preserve_fragment_on_redirect_url_ != location;
1402 }
1403 
IsSafeRedirect(const GURL & location)1404 bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
1405   // HTTP is always safe.
1406   // TODO(pauljensen): Remove once crbug.com/146591 is fixed.
1407   if (location.is_valid() &&
1408       (location.scheme() == "http" || location.scheme() == "https")) {
1409     return true;
1410   }
1411   // Query URLRequestJobFactory as to whether |location| would be safe to
1412   // redirect to.
1413   return request_->context()->job_factory() &&
1414       request_->context()->job_factory()->IsSafeRedirectTarget(location);
1415 }
1416 
NeedsAuth()1417 bool URLRequestHttpJob::NeedsAuth() {
1418   int code = GetResponseCode();
1419   if (code == -1)
1420     return false;
1421 
1422   // Check if we need either Proxy or WWW Authentication. This could happen
1423   // because we either provided no auth info, or provided incorrect info.
1424   switch (code) {
1425     case 407:
1426       if (proxy_auth_state_ == AUTH_STATE_CANCELED)
1427         return false;
1428       proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
1429       return true;
1430     case 401:
1431       if (server_auth_state_ == AUTH_STATE_CANCELED)
1432         return false;
1433       server_auth_state_ = AUTH_STATE_NEED_AUTH;
1434       return true;
1435   }
1436   return false;
1437 }
1438 
GetAuthChallengeInfo()1439 std::unique_ptr<AuthChallengeInfo> URLRequestHttpJob::GetAuthChallengeInfo() {
1440   DCHECK(transaction_.get());
1441   DCHECK(response_info_);
1442 
1443   // sanity checks:
1444   DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
1445          server_auth_state_ == AUTH_STATE_NEED_AUTH);
1446   DCHECK((GetResponseHeaders()->response_code() == HTTP_UNAUTHORIZED) ||
1447          (GetResponseHeaders()->response_code() ==
1448           HTTP_PROXY_AUTHENTICATION_REQUIRED));
1449 
1450   if (!response_info_->auth_challenge.has_value())
1451     return nullptr;
1452   return std::make_unique<AuthChallengeInfo>(
1453       response_info_->auth_challenge.value());
1454 }
1455 
SetAuth(const AuthCredentials & credentials)1456 void URLRequestHttpJob::SetAuth(const AuthCredentials& credentials) {
1457   DCHECK(transaction_.get());
1458 
1459   // Proxy gets set first, then WWW.
1460   if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1461     proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
1462   } else {
1463     DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
1464     server_auth_state_ = AUTH_STATE_HAVE_AUTH;
1465   }
1466 
1467   RestartTransactionWithAuth(credentials);
1468 }
1469 
CancelAuth()1470 void URLRequestHttpJob::CancelAuth() {
1471   if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1472     proxy_auth_state_ = AUTH_STATE_CANCELED;
1473   } else {
1474     DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
1475     server_auth_state_ = AUTH_STATE_CANCELED;
1476   }
1477 
1478   // The above lines should ensure this is the case.
1479   DCHECK(!NeedsAuth());
1480 
1481   // Let the consumer read the HTTP error page. NeedsAuth() should now return
1482   // false, so NotifyHeadersComplete() should not request auth from the client
1483   // again.
1484   //
1485   // Have to do this via PostTask to avoid re-entrantly calling into the
1486   // consumer.
1487   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1488       FROM_HERE, base::BindOnce(&URLRequestHttpJob::NotifyFinalHeadersReceived,
1489                                 weak_factory_.GetWeakPtr()));
1490 }
1491 
ContinueWithCertificate(scoped_refptr<X509Certificate> client_cert,scoped_refptr<SSLPrivateKey> client_private_key)1492 void URLRequestHttpJob::ContinueWithCertificate(
1493     scoped_refptr<X509Certificate> client_cert,
1494     scoped_refptr<SSLPrivateKey> client_private_key) {
1495   DCHECK(transaction_);
1496 
1497   DCHECK(!response_info_) << "should not have a response yet";
1498   DCHECK(!override_response_headers_);
1499   receive_headers_end_ = base::TimeTicks();
1500 
1501   ResetTimer();
1502 
1503   int rv = transaction_->RestartWithCertificate(
1504       std::move(client_cert), std::move(client_private_key),
1505       base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1506                      base::Unretained(this)));
1507   if (rv == ERR_IO_PENDING)
1508     return;
1509 
1510   // The transaction started synchronously, but we need to notify the
1511   // URLRequest delegate via the message loop.
1512   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1513       FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1514                                 weak_factory_.GetWeakPtr(), rv));
1515 }
1516 
ContinueDespiteLastError()1517 void URLRequestHttpJob::ContinueDespiteLastError() {
1518   // If the transaction was destroyed, then the job was cancelled.
1519   if (!transaction_.get())
1520     return;
1521 
1522   DCHECK(!response_info_) << "should not have a response yet";
1523   DCHECK(!override_response_headers_);
1524   receive_headers_end_ = base::TimeTicks();
1525 
1526   ResetTimer();
1527 
1528   int rv = transaction_->RestartIgnoringLastError(base::BindOnce(
1529       &URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
1530   if (rv == ERR_IO_PENDING)
1531     return;
1532 
1533   // The transaction started synchronously, but we need to notify the
1534   // URLRequest delegate via the message loop.
1535   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1536       FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1537                                 weak_factory_.GetWeakPtr(), rv));
1538 }
1539 
ShouldFixMismatchedContentLength(int rv) const1540 bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const {
1541   // Some servers send the body compressed, but specify the content length as
1542   // the uncompressed size. Although this violates the HTTP spec we want to
1543   // support it (as IE and FireFox do), but *only* for an exact match.
1544   // See http://crbug.com/79694.
1545   if (rv == ERR_CONTENT_LENGTH_MISMATCH ||
1546       rv == ERR_INCOMPLETE_CHUNKED_ENCODING) {
1547     if (request_->response_headers()) {
1548       int64_t expected_length =
1549           request_->response_headers()->GetContentLength();
1550       VLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
1551               << " content-length = " << expected_length
1552               << " pre total = " << prefilter_bytes_read()
1553               << " post total = " << postfilter_bytes_read();
1554       if (postfilter_bytes_read() == expected_length) {
1555         // Clear the error.
1556         return true;
1557       }
1558     }
1559   }
1560   return false;
1561 }
1562 
ReadRawData(IOBuffer * buf,int buf_size)1563 int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) {
1564   DCHECK_NE(buf_size, 0);
1565   DCHECK(!read_in_progress_);
1566 
1567   int rv =
1568       transaction_->Read(buf, buf_size,
1569                          base::BindOnce(&URLRequestHttpJob::OnReadCompleted,
1570                                         base::Unretained(this)));
1571 
1572   if (ShouldFixMismatchedContentLength(rv))
1573     rv = OK;
1574 
1575   if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING))
1576     DoneWithRequest(FINISHED);
1577 
1578   if (rv == ERR_IO_PENDING)
1579     read_in_progress_ = true;
1580 
1581   return rv;
1582 }
1583 
GetTotalReceivedBytes() const1584 int64_t URLRequestHttpJob::GetTotalReceivedBytes() const {
1585   int64_t total_received_bytes =
1586       total_received_bytes_from_previous_transactions_;
1587   if (transaction_)
1588     total_received_bytes += transaction_->GetTotalReceivedBytes();
1589   return total_received_bytes;
1590 }
1591 
GetTotalSentBytes() const1592 int64_t URLRequestHttpJob::GetTotalSentBytes() const {
1593   int64_t total_sent_bytes = total_sent_bytes_from_previous_transactions_;
1594   if (transaction_)
1595     total_sent_bytes += transaction_->GetTotalSentBytes();
1596   return total_sent_bytes;
1597 }
1598 
DoneReading()1599 void URLRequestHttpJob::DoneReading() {
1600   if (transaction_) {
1601     transaction_->DoneReading();
1602   }
1603   DoneWithRequest(FINISHED);
1604 }
1605 
DoneReadingRedirectResponse()1606 void URLRequestHttpJob::DoneReadingRedirectResponse() {
1607   if (transaction_) {
1608     DCHECK(!override_response_info_);
1609     if (transaction_->GetResponseInfo()->headers->IsRedirect(nullptr)) {
1610       // If the original headers indicate a redirect, go ahead and cache the
1611       // response, even if the |override_response_headers_| are a redirect to
1612       // another location.
1613       transaction_->DoneReading();
1614     } else {
1615       // Otherwise, |override_response_headers_| must be non-NULL and contain
1616       // bogus headers indicating a redirect.
1617       DCHECK(override_response_headers_.get());
1618       DCHECK(override_response_headers_->IsRedirect(nullptr));
1619       transaction_->StopCaching();
1620     }
1621   }
1622   DoneWithRequest(FINISHED);
1623 }
1624 
GetResponseRemoteEndpoint() const1625 IPEndPoint URLRequestHttpJob::GetResponseRemoteEndpoint() const {
1626   return response_info_ ? response_info_->remote_endpoint : IPEndPoint();
1627 }
1628 
RecordTimer()1629 void URLRequestHttpJob::RecordTimer() {
1630   if (request_creation_time_.is_null()) {
1631     NOTREACHED()
1632         << "The same transaction shouldn't start twice without new timing.";
1633     return;
1634   }
1635 
1636   base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
1637   request_creation_time_ = base::Time();
1638 
1639   UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
1640 
1641   // Record additional metrics for TLS 1.3 servers for Google hosts. Most
1642   // Google hosts are known to implement 0-RTT, so this gives more targeted
1643   // metrics as we initially roll out client support. This is to help measure
1644   // the impact of enabling 0-RTT. The effects of 0-RTT will be muted because
1645   // not all TLS 1.3 servers enable 0-RTT, and only the first round-trip on a
1646   // connection makes use of 0-RTT. However, 0-RTT can affect how requests are
1647   // bound to connections and which connections offer resumption. We look at
1648   // all TLS 1.3 responses for an apples-to-apples comparison.
1649   // TODO(crbug.com/641225): Remove these metrics after launching 0-RTT.
1650   if (transaction_ && transaction_->GetResponseInfo() &&
1651       IsTLS13OverTCP(*transaction_->GetResponseInfo()) &&
1652       HasGoogleHost(request()->url())) {
1653     base::UmaHistogramMediumTimes("Net.HttpTimeToFirstByte.TLS13.Google",
1654                                   to_start);
1655   }
1656 }
1657 
ResetTimer()1658 void URLRequestHttpJob::ResetTimer() {
1659   if (!request_creation_time_.is_null()) {
1660     NOTREACHED()
1661         << "The timer was reset before it was recorded.";
1662     return;
1663   }
1664   request_creation_time_ = base::Time::Now();
1665 }
1666 
SetRequestHeadersCallback(RequestHeadersCallback callback)1667 void URLRequestHttpJob::SetRequestHeadersCallback(
1668     RequestHeadersCallback callback) {
1669   DCHECK(!transaction_);
1670   DCHECK(!request_headers_callback_);
1671   request_headers_callback_ = std::move(callback);
1672 }
1673 
SetEarlyResponseHeadersCallback(ResponseHeadersCallback callback)1674 void URLRequestHttpJob::SetEarlyResponseHeadersCallback(
1675     ResponseHeadersCallback callback) {
1676   DCHECK(!transaction_);
1677   DCHECK(!early_response_headers_callback_);
1678   early_response_headers_callback_ = std::move(callback);
1679 }
1680 
SetIsSharedDictionaryReadAllowedCallback(base::RepeatingCallback<bool ()> callback)1681 void URLRequestHttpJob::SetIsSharedDictionaryReadAllowedCallback(
1682     base::RepeatingCallback<bool()> callback) {
1683   DCHECK(!transaction_);
1684   DCHECK(!is_shared_dictionary_read_allowed_callback_);
1685   is_shared_dictionary_read_allowed_callback_ = std::move(callback);
1686 }
1687 
SetResponseHeadersCallback(ResponseHeadersCallback callback)1688 void URLRequestHttpJob::SetResponseHeadersCallback(
1689     ResponseHeadersCallback callback) {
1690   DCHECK(!transaction_);
1691   DCHECK(!response_headers_callback_);
1692   response_headers_callback_ = std::move(callback);
1693 }
1694 
RecordCompletionHistograms(CompletionCause reason)1695 void URLRequestHttpJob::RecordCompletionHistograms(CompletionCause reason) {
1696   if (start_time_.is_null())
1697     return;
1698 
1699   base::TimeDelta total_time = base::TimeTicks::Now() - start_time_;
1700   UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time);
1701 
1702   if (reason == FINISHED) {
1703     UmaHistogramTimes(
1704         base::StringPrintf("Net.HttpJob.TotalTimeSuccess.Priority%d",
1705                            request()->priority()),
1706         total_time);
1707     UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time);
1708   } else {
1709     UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time);
1710   }
1711 
1712   if (response_info_) {
1713     // QUIC (by default) supports https scheme only, thus track https URLs only
1714     // for QUIC.
1715     bool is_https_google = request() && request()->url().SchemeIs("https") &&
1716                            HasGoogleHost(request()->url());
1717     bool used_quic = response_info_->DidUseQuic();
1718     if (is_https_google) {
1719       if (used_quic) {
1720         UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic",
1721                                    total_time);
1722       }
1723     }
1724 
1725     // Record metrics for TLS 1.3 to measure the impact of 0-RTT. See comment in
1726     // RecordTimer().
1727     //
1728     // TODO(https://crbug.com/641225): Remove these metrics after launching
1729     // 0-RTT.
1730     if (IsTLS13OverTCP(*response_info_) && is_https_google) {
1731       base::UmaHistogramTimes("Net.HttpJob.TotalTime.TLS13.Google", total_time);
1732     }
1733 
1734     UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
1735                                 prefilter_bytes_read(), 1, 50000000, 50);
1736     if (response_info_->was_cached) {
1737       UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
1738       UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache",
1739                                   prefilter_bytes_read(), 1, 50000000, 50);
1740     } else {
1741       UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
1742       if (response_info_->was_mdl_match) {
1743         UMA_HISTOGRAM_CUSTOM_COUNTS(
1744             "Net.HttpJob.IpProtection.AllowListMatch.BytesSent",
1745             GetTotalSentBytes(), 1, 50000000, 50);
1746 
1747         UMA_HISTOGRAM_CUSTOM_COUNTS(
1748             "Net.HttpJob.IpProtection.AllowListMatch.PrefilterBytesRead.Net",
1749             prefilter_bytes_read(), 1, 50000000, 50);
1750       }
1751       if (response_info_->was_ip_protected) {
1752         UMA_HISTOGRAM_TIMES("Net.HttpJob.IpProtection.TotalTimeNotCached",
1753                             total_time);
1754 
1755         UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.IpProtection.BytesSent",
1756                                     GetTotalSentBytes(), 1, 50000000, 50);
1757 
1758         UMA_HISTOGRAM_CUSTOM_COUNTS(
1759             "Net.HttpJob.IpProtection.PrefilterBytesRead.Net",
1760             prefilter_bytes_read(), 1, 50000000, 50);
1761       }
1762       UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net",
1763                                   prefilter_bytes_read(), 1, 50000000, 50);
1764 
1765       if (request_->ad_tagged()) {
1766         UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Ads.Net",
1767                                     prefilter_bytes_read(), 1, 50000000, 50);
1768       }
1769 
1770       if (is_https_google && used_quic) {
1771         UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTimeNotCached.Secure.Quic",
1772                                    total_time);
1773       }
1774     }
1775   }
1776 
1777   start_time_ = base::TimeTicks();
1778 }
1779 
DoneWithRequest(CompletionCause reason)1780 void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) {
1781   if (done_)
1782     return;
1783   done_ = true;
1784 
1785   // Notify NetworkQualityEstimator.
1786   NetworkQualityEstimator* network_quality_estimator =
1787       request()->context()->network_quality_estimator();
1788   if (network_quality_estimator) {
1789     network_quality_estimator->NotifyRequestCompleted(*request());
1790   }
1791 
1792   RecordCompletionHistograms(reason);
1793   request()->set_received_response_content_length(prefilter_bytes_read());
1794 }
1795 
GetResponseHeaders() const1796 HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const {
1797   if (override_response_info_) {
1798     DCHECK(!transaction_.get());
1799     return override_response_info_->headers.get();
1800   }
1801 
1802   DCHECK(transaction_.get());
1803   DCHECK(transaction_->GetResponseInfo());
1804 
1805   return override_response_headers_.get() ?
1806              override_response_headers_.get() :
1807              transaction_->GetResponseInfo()->headers.get();
1808 }
1809 
NotifyURLRequestDestroyed()1810 void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1811   awaiting_callback_ = false;
1812 
1813   // Notify NetworkQualityEstimator.
1814   NetworkQualityEstimator* network_quality_estimator =
1815       request()->context()->network_quality_estimator();
1816   if (network_quality_estimator)
1817     network_quality_estimator->NotifyURLRequestDestroyed(*request());
1818 }
1819 
ShouldAddCookieHeader() const1820 bool URLRequestHttpJob::ShouldAddCookieHeader() const {
1821   // Read cookies whenever allow_credentials() is true, even if the PrivacyMode
1822   // is being overridden by NetworkDelegate and will eventually block them, as
1823   // blocked cookies still need to be logged in that case.
1824   return request_->context()->cookie_store() && request_->allow_credentials();
1825 }
1826 
ShouldRecordPartitionedCookieUsage() const1827 bool URLRequestHttpJob::ShouldRecordPartitionedCookieUsage() const {
1828   return request_->cookie_partition_key().has_value();
1829 }
1830 
1831 }  // namespace net
1832