Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_factory_impl_job_controller.h" | 5 #include "net/http/http_stream_factory_impl_job_controller.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 | 91 |
| 92 void HttpStreamFactoryImpl::JobController::Preconnect( | 92 void HttpStreamFactoryImpl::JobController::Preconnect( |
| 93 int num_streams, | 93 int num_streams, |
| 94 const HttpRequestInfo& request_info, | 94 const HttpRequestInfo& request_info, |
| 95 const SSLConfig& server_ssl_config, | 95 const SSLConfig& server_ssl_config, |
| 96 const SSLConfig& proxy_ssl_config) { | 96 const SSLConfig& proxy_ssl_config) { |
| 97 DCHECK(!main_job_); | 97 DCHECK(!main_job_); |
| 98 DCHECK(!alternative_job_); | 98 DCHECK(!alternative_job_); |
| 99 | 99 |
| 100 is_preconnect_ = true; | 100 is_preconnect_ = true; |
| 101 | |
| 102 can_start_alternative_proxy_job_ = | |
| 103 session_->params().race_preconnects_to_http2_proxies; | |
| 104 | |
| 101 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | 105 HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
| 102 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | 106 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
| 103 | 107 |
| 104 const AlternativeService alternative_service = GetAlternativeServiceFor( | 108 const AlternativeService alternative_service = GetAlternativeServiceFor( |
| 105 request_info, nullptr, HttpStreamRequest::HTTP_STREAM); | 109 request_info, nullptr, HttpStreamRequest::HTTP_STREAM); |
| 106 | 110 |
| 107 if (alternative_service.protocol != kProtoUnknown) { | 111 if (alternative_service.protocol != kProtoUnknown) { |
| 108 if (session_->params().quic_disable_preconnect_if_0rtt && | 112 if (session_->params().quic_disable_preconnect_if_0rtt && |
| 109 alternative_service.protocol == kProtoQUIC && | 113 alternative_service.protocol == kProtoQUIC && |
| 110 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( | 114 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 HttpStreamRequest::StreamType stream_type) { | 391 HttpStreamRequest::StreamType stream_type) { |
| 388 DCHECK(job); | 392 DCHECK(job); |
| 389 | 393 |
| 390 ProxyServer alternative_proxy_server; | 394 ProxyServer alternative_proxy_server; |
| 391 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), | 395 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), |
| 392 request_info.url, | 396 request_info.url, |
| 393 &alternative_proxy_server)) { | 397 &alternative_proxy_server)) { |
| 394 return; | 398 return; |
| 395 } | 399 } |
| 396 | 400 |
| 397 DCHECK(main_job_); | 401 DCHECK(is_preconnect_ || job->job_type() == MAIN); |
| 398 DCHECK_EQ(MAIN, job->job_type()); | 402 DCHECK_EQ(main_job_.get(), job); |
|
Ryan Hamilton
2017/01/24 19:36:59
The previous line suggest that this job might not
| |
| 399 DCHECK(!alternative_job_); | 403 DCHECK(!alternative_job_); |
| 400 DCHECK(!main_job_is_blocked_); | 404 DCHECK(!main_job_is_blocked_); |
| 401 | 405 |
| 406 if (is_preconnect_) { | |
| 407 // Restrict the number of streams to 1 since the proxy server supports spdy. | |
| 408 job->RestrictNumStreamsToOne(); | |
| 409 } | |
|
Ryan Hamilton
2017/01/24 19:36:59
So this restricts the number of streams on the mai
| |
| 410 | |
| 402 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | 411 HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
| 403 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | 412 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
| 404 | 413 |
| 405 alternative_job_.reset(job_factory_->CreateJob( | 414 alternative_job_.reset(job_factory_->CreateJob( |
| 406 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, | 415 this, is_preconnect_ ? PRECONNECT : ALTERNATIVE, session_, request_info, |
| 407 proxy_ssl_config, destination, origin_url, alternative_proxy_server, | 416 priority, server_ssl_config, proxy_ssl_config, destination, origin_url, |
| 408 job->net_log().net_log())); | 417 alternative_proxy_server, job->net_log().net_log())); |
| 409 AttachJob(alternative_job_.get()); | 418 |
| 419 if (!is_preconnect_) { | |
| 420 // Preconnect jobs do not have an associated request. So, the preconnect | |
| 421 // job can't be attached. | |
| 422 AttachJob(alternative_job_.get()); | |
| 423 } | |
| 410 | 424 |
| 411 can_start_alternative_proxy_job_ = false; | 425 can_start_alternative_proxy_job_ = false; |
| 412 main_job_is_blocked_ = true; | 426 main_job_is_blocked_ = true; |
|
Ryan Hamilton
2017/01/24 19:36:59
I believe this all means that the main job will no
| |
| 413 | 427 |
| 414 base::ThreadTaskRunnerHandle::Get()->PostTask( | 428 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 415 FROM_HERE, | 429 FROM_HERE, |
| 416 base::Bind( | 430 base::Bind( |
| 417 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, | 431 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, |
| 418 ptr_factory_.GetWeakPtr())); | 432 ptr_factory_.GetWeakPtr())); |
| 419 } | 433 } |
| 420 | 434 |
| 421 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( | 435 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( |
| 422 Job* job, | 436 Job* job, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 factory->OnNewSpdySessionReady(spdy_session, direct, used_ssl_config, | 493 factory->OnNewSpdySessionReady(spdy_session, direct, used_ssl_config, |
| 480 used_proxy_info, was_alpn_negotiated, | 494 used_proxy_info, was_alpn_negotiated, |
| 481 negotiated_protocol, using_spdy, net_log); | 495 negotiated_protocol, using_spdy, net_log); |
| 482 } | 496 } |
| 483 if (is_job_orphaned) { | 497 if (is_job_orphaned) { |
| 484 OnOrphanedJobComplete(job); | 498 OnOrphanedJobComplete(job); |
| 485 } | 499 } |
| 486 } | 500 } |
| 487 | 501 |
| 488 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { | 502 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { |
| 489 DCHECK_EQ(main_job_.get(), job); | 503 DCHECK(job); |
| 490 main_job_.reset(); | 504 DCHECK(main_job_.get() == job || alternative_job_.get() == job); |
| 491 factory_->OnPreconnectsCompleteInternal(); | 505 DCHECK_EQ(PRECONNECT, job->job_type()); |
| 492 MaybeNotifyFactoryOfCompletion(); | 506 if (is_preconnect_ && main_job_ && alternative_job_) { |
| 507 UMA_HISTOGRAM_EXACT_LINEAR( | |
| 508 "Net.QuicAlternativeProxy.PreconnectRace.FirstJobFinished", 1, 2); | |
|
Ryan Hamilton
2017/01/24 19:36:59
I'm not sure "FirstJobFinished" adds any value to
| |
| 509 } | |
| 510 | |
| 511 // Note that completion of a preconnect job does not indicate that | |
| 512 // preconnection was actually successful since the socket layer currently does | |
| 513 // not provide the success or failure status of the (possibly) multiple | |
| 514 // preconnect sockets. | |
| 515 if (job == main_job_.get()) | |
| 516 main_job_.reset(); | |
| 517 | |
| 518 if (job == alternative_job_.get()) | |
| 519 alternative_job_.reset(); | |
| 520 | |
| 521 if (!main_job_ && !alternative_job_) { | |
| 522 factory_->OnPreconnectsCompleteInternal(); | |
| 523 MaybeNotifyFactoryOfCompletion(); | |
| 524 } | |
| 493 } | 525 } |
| 494 | 526 |
| 495 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( | 527 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( |
| 496 const Job* job) { | 528 const Job* job) { |
| 497 if (job->job_type() == MAIN) { | 529 if (job->job_type() == MAIN) { |
| 498 DCHECK_EQ(main_job_.get(), job); | 530 DCHECK_EQ(main_job_.get(), job); |
| 499 main_job_.reset(); | 531 main_job_.reset(); |
| 500 } else { | 532 } else { |
| 501 DCHECK_EQ(alternative_job_.get(), job); | 533 DCHECK_EQ(alternative_job_.get(), job); |
| 502 alternative_job_.reset(); | 534 alternative_job_.reset(); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 696 can_start_alternative_proxy_job_ = true; | 728 can_start_alternative_proxy_job_ = true; |
| 697 } | 729 } |
| 698 // Even if |alternative_job| has already finished, it will not have notified | 730 // Even if |alternative_job| has already finished, it will not have notified |
| 699 // the request yet, since we defer that to the next iteration of the | 731 // the request yet, since we defer that to the next iteration of the |
| 700 // MessageLoop, so starting |main_job_| is always safe. | 732 // MessageLoop, so starting |main_job_| is always safe. |
| 701 main_job_->Start(request_->stream_type()); | 733 main_job_->Start(request_->stream_type()); |
| 702 } | 734 } |
| 703 | 735 |
| 704 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { | 736 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { |
| 705 DCHECK(job); | 737 DCHECK(job); |
| 738 DCHECK(!is_preconnect_); | |
| 706 factory_->request_map_[job] = request_; | 739 factory_->request_map_[job] = request_; |
| 707 } | 740 } |
| 708 | 741 |
| 709 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { | 742 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { |
| 710 DCHECK(request_); | 743 DCHECK(request_); |
| 711 DCHECK(job); | 744 DCHECK(job); |
| 712 DCHECK(job == alternative_job_.get() || job == main_job_.get()); | 745 DCHECK(job == alternative_job_.get() || job == main_job_.get()); |
| 713 DCHECK(!job_bound_); | 746 DCHECK(!job_bound_); |
| 714 DCHECK(!bound_job_); | 747 DCHECK(!bound_job_); |
| 715 | 748 |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1030 // already been started. | 1063 // already been started. |
| 1031 return false; | 1064 return false; |
| 1032 } | 1065 } |
| 1033 | 1066 |
| 1034 if (job->job_type() == ALTERNATIVE) { | 1067 if (job->job_type() == ALTERNATIVE) { |
| 1035 // If |job| is using alternative service, then alternative proxy server | 1068 // If |job| is using alternative service, then alternative proxy server |
| 1036 // should not be used. | 1069 // should not be used. |
| 1037 return false; | 1070 return false; |
| 1038 } | 1071 } |
| 1039 | 1072 |
| 1040 if (is_preconnect_ || job->job_type() == PRECONNECT) { | |
| 1041 // Preconnects should be fetched using only the main job to keep the | |
| 1042 // resource utilization down. | |
| 1043 return false; | |
|
Ryan Hamilton
2017/01/24 19:36:59
you could probably add a DCHECK here checking the
| |
| 1044 } | |
| 1045 | |
| 1046 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { | 1073 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { |
| 1047 // Alternative proxy server job can be created only if |job| fetches the | 1074 // Alternative proxy server job can be created only if |job| fetches the |
| 1048 // |request_| through a non-QUIC proxy. | 1075 // |request_| through a non-QUIC proxy. |
| 1049 return false; | 1076 return false; |
| 1050 } | 1077 } |
| 1051 | 1078 |
| 1052 if (!url.SchemeIs(url::kHttpScheme)) { | 1079 if (!url.SchemeIs(url::kHttpScheme)) { |
| 1053 // Only HTTP URLs can be fetched through alternative proxy server, since the | 1080 // Only HTTP URLs can be fetched through alternative proxy server, since the |
| 1054 // alternative proxy server may not support fetching of URLs with other | 1081 // alternative proxy server may not support fetching of URLs with other |
| 1055 // schemes. | 1082 // schemes. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1103 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, | 1130 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, |
| 1104 proxy_server_used); | 1131 proxy_server_used); |
| 1105 return; | 1132 return; |
| 1106 } | 1133 } |
| 1107 | 1134 |
| 1108 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, | 1135 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, |
| 1109 proxy_server_used); | 1136 proxy_server_used); |
| 1110 } | 1137 } |
| 1111 | 1138 |
| 1112 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() { | 1139 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() { |
| 1113 if (!alternative_job_ || !request_) | 1140 if (!alternative_job_) |
| 1114 return; | 1141 return; |
| 1115 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); | 1142 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); |
| 1116 alternative_job_->Start(request_->stream_type()); | 1143 |
| 1144 if (!is_preconnect_) { | |
| 1145 if (!request_) | |
| 1146 return; | |
| 1147 DCHECK(alternative_job_->alternative_proxy_server().is_quic()); | |
| 1148 alternative_job_->Start(request_->stream_type()); | |
| 1149 } else { | |
| 1150 // Restrict the number of streams to 1 since the alternative proxy server | |
| 1151 // supports request priorities. | |
| 1152 DCHECK(alternative_job_->alternative_proxy_server().is_quic()); | |
| 1153 alternative_job_->Preconnect(1 /* num_streams */); | |
| 1154 } | |
|
Ryan Hamilton
2017/01/24 19:36:59
nit: I'd structure this slightly differently:
if
| |
| 1117 } | 1155 } |
| 1118 | 1156 |
| 1119 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { | 1157 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { |
| 1120 return !request_ || (job_bound_ && bound_job_ != job); | 1158 return !request_ || (job_bound_ && bound_job_ != job); |
| 1121 } | 1159 } |
| 1122 | 1160 |
| 1123 } // namespace net | 1161 } // namespace net |
| OLD | NEW |