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