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_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 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 HttpStreamRequest::StreamType stream_type) { | 387 HttpStreamRequest::StreamType stream_type) { |
| 384 DCHECK(job); | 388 DCHECK(job); |
| 385 | 389 |
| 386 ProxyServer alternative_proxy_server; | 390 ProxyServer alternative_proxy_server; |
| 387 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), | 391 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), |
| 388 request_info.url, | 392 request_info.url, |
| 389 &alternative_proxy_server)) { | 393 &alternative_proxy_server)) { |
| 390 return; | 394 return; |
| 391 } | 395 } |
| 392 | 396 |
| 393 DCHECK(main_job_); | 397 DCHECK(is_preconnect_ || job->job_type() == MAIN); |
| 394 DCHECK_EQ(MAIN, job->job_type()); | 398 DCHECK_EQ(main_job_.get(), job); |
| 395 DCHECK(!alternative_job_); | 399 DCHECK(!alternative_job_); |
| 396 DCHECK(!main_job_is_blocked_); | 400 DCHECK(!main_job_is_blocked_); |
| 401 DCHECK(alternative_proxy_server.is_quic()); | |
|
Ryan Hamilton
2017/01/23 18:05:53
Why is this guaranteed to be true?
tbansal1
2017/01/23 21:48:22
Removed. (Currently it is true because QUIC is the
Ryan Hamilton
2017/01/24 19:36:59
We also support HTTP/2 based Alt-Svc.
| |
| 402 | |
| 403 if (is_preconnect_) { | |
| 404 // Restrict the number of streams to 1 since the proxy server supports spdy. | |
| 405 job->RestrictNumStreamsToOne(); | |
|
Ryan Hamilton
2017/01/23 18:05:53
It seems like this is a bit orthogonal to racing a
tbansal1
2017/01/23 21:48:22
The preconnections for non-proxy http2 jobs restri
Ryan Hamilton
2017/01/24 19:36:59
Ah, I see. You're saying that "restrict to 1 strea
| |
| 406 } | |
| 397 | 407 |
| 398 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | 408 HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
| 399 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | 409 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
| 400 | 410 |
| 401 alternative_job_.reset(job_factory_->CreateJob( | 411 alternative_job_.reset(job_factory_->CreateJob( |
| 402 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, | 412 this, is_preconnect_ ? PRECONNECT : ALTERNATIVE, session_, request_info, |
| 403 proxy_ssl_config, destination, origin_url, alternative_proxy_server, | 413 priority, server_ssl_config, proxy_ssl_config, destination, origin_url, |
| 404 job->net_log().net_log())); | 414 alternative_proxy_server, job->net_log().net_log())); |
| 405 AttachJob(alternative_job_.get()); | 415 |
| 416 if (!is_preconnect_) { | |
| 417 // Preconnect jobs do not have an associated request. So, the preconnect | |
| 418 // job can't be attached. | |
| 419 AttachJob(alternative_job_.get()); | |
| 420 } | |
| 406 | 421 |
| 407 can_start_alternative_proxy_job_ = false; | 422 can_start_alternative_proxy_job_ = false; |
| 408 main_job_is_blocked_ = true; | 423 main_job_is_blocked_ = true; |
| 409 | 424 |
| 410 base::ThreadTaskRunnerHandle::Get()->PostTask( | 425 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 411 FROM_HERE, | 426 FROM_HERE, |
| 412 base::Bind( | 427 base::Bind( |
| 413 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, | 428 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, |
| 414 ptr_factory_.GetWeakPtr())); | 429 ptr_factory_.GetWeakPtr())); |
| 415 } | 430 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 factory->OnNewSpdySessionReady(spdy_session, direct, used_ssl_config, | 490 factory->OnNewSpdySessionReady(spdy_session, direct, used_ssl_config, |
| 476 used_proxy_info, was_alpn_negotiated, | 491 used_proxy_info, was_alpn_negotiated, |
| 477 negotiated_protocol, using_spdy, net_log); | 492 negotiated_protocol, using_spdy, net_log); |
| 478 } | 493 } |
| 479 if (is_job_orphaned) { | 494 if (is_job_orphaned) { |
| 480 OnOrphanedJobComplete(job); | 495 OnOrphanedJobComplete(job); |
| 481 } | 496 } |
| 482 } | 497 } |
| 483 | 498 |
| 484 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { | 499 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { |
| 485 DCHECK_EQ(main_job_.get(), job); | 500 DCHECK(job); |
| 486 main_job_.reset(); | 501 DCHECK(main_job_.get() == job || alternative_job_.get() == job); |
| 487 factory_->OnPreconnectsCompleteInternal(); | 502 DCHECK_EQ(PRECONNECT, job->job_type()); |
| 488 MaybeNotifyFactoryOfCompletion(); | 503 if (is_preconnect_ && main_job_ && alternative_job_) { |
| 504 UMA_HISTOGRAM_EXACT_LINEAR("Net.QuicAlternativeProxy.PreconnectJobsRaced", | |
| 505 1, 2); | |
|
Ryan Hamilton
2017/01/23 18:05:53
I don't understand what this histogram is recordin
tbansal1
2017/01/23 21:48:23
It is just recording how many times preconnect job
| |
| 506 } | |
| 507 | |
| 508 // Note that completion of a preconnect job does not indicate that | |
| 509 // preconnection was actually successful since the socket layer currently does | |
| 510 // not provide the success or failure status of the (possibly) multiple | |
| 511 // preconnect sockets. | |
| 512 if (job == main_job_.get()) | |
| 513 main_job_.reset(); | |
| 514 | |
| 515 if (job == alternative_job_.get()) | |
| 516 alternative_job_.reset(); | |
| 517 | |
| 518 if (!main_job_ && !alternative_job_) { | |
| 519 factory_->OnPreconnectsCompleteInternal(); | |
| 520 MaybeNotifyFactoryOfCompletion(); | |
| 521 } | |
| 489 } | 522 } |
| 490 | 523 |
| 491 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( | 524 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( |
| 492 const Job* job) { | 525 const Job* job) { |
| 493 if (job->job_type() == MAIN) { | 526 if (job->job_type() == MAIN) { |
| 494 DCHECK_EQ(main_job_.get(), job); | 527 DCHECK_EQ(main_job_.get(), job); |
| 495 main_job_.reset(); | 528 main_job_.reset(); |
| 496 } else { | 529 } else { |
| 497 DCHECK_EQ(alternative_job_.get(), job); | 530 DCHECK_EQ(alternative_job_.get(), job); |
| 498 alternative_job_.reset(); | 531 alternative_job_.reset(); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 can_start_alternative_proxy_job_ = true; | 708 can_start_alternative_proxy_job_ = true; |
| 676 } | 709 } |
| 677 // Even if |alternative_job| has already finished, it will not have notified | 710 // Even if |alternative_job| has already finished, it will not have notified |
| 678 // the request yet, since we defer that to the next iteration of the | 711 // the request yet, since we defer that to the next iteration of the |
| 679 // MessageLoop, so starting |main_job_| is always safe. | 712 // MessageLoop, so starting |main_job_| is always safe. |
| 680 main_job_->Start(request_->stream_type()); | 713 main_job_->Start(request_->stream_type()); |
| 681 } | 714 } |
| 682 | 715 |
| 683 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { | 716 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { |
| 684 DCHECK(job); | 717 DCHECK(job); |
| 718 DCHECK(!is_preconnect_); | |
| 685 factory_->request_map_[job] = request_; | 719 factory_->request_map_[job] = request_; |
| 686 } | 720 } |
| 687 | 721 |
| 688 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { | 722 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { |
| 689 DCHECK(request_); | 723 DCHECK(request_); |
| 690 DCHECK(job); | 724 DCHECK(job); |
| 691 DCHECK(job == alternative_job_.get() || job == main_job_.get()); | 725 DCHECK(job == alternative_job_.get() || job == main_job_.get()); |
| 692 DCHECK(!job_bound_); | 726 DCHECK(!job_bound_); |
| 693 DCHECK(!bound_job_); | 727 DCHECK(!bound_job_); |
| 694 | 728 |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 999 // already been started. | 1033 // already been started. |
| 1000 return false; | 1034 return false; |
| 1001 } | 1035 } |
| 1002 | 1036 |
| 1003 if (job->job_type() == ALTERNATIVE) { | 1037 if (job->job_type() == ALTERNATIVE) { |
| 1004 // If |job| is using alternative service, then alternative proxy server | 1038 // If |job| is using alternative service, then alternative proxy server |
| 1005 // should not be used. | 1039 // should not be used. |
| 1006 return false; | 1040 return false; |
| 1007 } | 1041 } |
| 1008 | 1042 |
| 1009 if (is_preconnect_ || job->job_type() == PRECONNECT) { | |
| 1010 // Preconnects should be fetched using only the main job to keep the | |
| 1011 // resource utilization down. | |
| 1012 return false; | |
| 1013 } | |
| 1014 | |
| 1015 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { | 1043 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { |
| 1016 // Alternative proxy server job can be created only if |job| fetches the | 1044 // Alternative proxy server job can be created only if |job| fetches the |
| 1017 // |request_| through a non-QUIC proxy. | 1045 // |request_| through a non-QUIC proxy. |
| 1018 return false; | 1046 return false; |
| 1019 } | 1047 } |
| 1020 | 1048 |
| 1021 if (!url.SchemeIs(url::kHttpScheme)) { | 1049 if (!url.SchemeIs(url::kHttpScheme)) { |
| 1022 // Only HTTP URLs can be fetched through alternative proxy server, since the | 1050 // Only HTTP URLs can be fetched through alternative proxy server, since the |
| 1023 // alternative proxy server may not support fetching of URLs with other | 1051 // alternative proxy server may not support fetching of URLs with other |
| 1024 // schemes. | 1052 // schemes. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1072 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, | 1100 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, |
| 1073 proxy_server_used); | 1101 proxy_server_used); |
| 1074 return; | 1102 return; |
| 1075 } | 1103 } |
| 1076 | 1104 |
| 1077 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, | 1105 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, |
| 1078 proxy_server_used); | 1106 proxy_server_used); |
| 1079 } | 1107 } |
| 1080 | 1108 |
| 1081 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() { | 1109 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() { |
| 1082 if (!alternative_job_ || !request_) | 1110 if (!alternative_job_) |
| 1083 return; | 1111 return; |
| 1084 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); | 1112 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); |
| 1085 alternative_job_->Start(request_->stream_type()); | 1113 |
| 1114 if (!is_preconnect_) { | |
| 1115 if (!request_) | |
| 1116 return; | |
| 1117 DCHECK(alternative_job_->alternative_proxy_server().is_quic()); | |
| 1118 alternative_job_->Start(request_->stream_type()); | |
| 1119 } else { | |
| 1120 // Restrict the number of streams to 1 since the alternative proxy server | |
| 1121 // supports request priorities. | |
| 1122 DCHECK(alternative_job_->alternative_proxy_server().is_quic()); | |
| 1123 alternative_job_->Preconnect(1 /* num_streams */); | |
| 1124 } | |
| 1086 } | 1125 } |
| 1087 | 1126 |
| 1088 } // namespace net | 1127 } // namespace net |
| OLD | NEW |