Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: net/http/http_stream_factory_impl_job_controller.cc

Issue 2814633003: Extract Proxy Resolution out of HttpStreamFactoryImpl::Job (Closed)
Patch Set: fix alt proxy tests Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 11 matching lines...) Expand all
22 #include "net/log/net_log_capture_mode.h" 22 #include "net/log/net_log_capture_mode.h"
23 #include "net/log/net_log_event_type.h" 23 #include "net/log/net_log_event_type.h"
24 #include "net/log/net_log_source.h" 24 #include "net/log/net_log_source.h"
25 #include "net/log/net_log_with_source.h" 25 #include "net/log/net_log_with_source.h"
26 #include "net/proxy/proxy_server.h" 26 #include "net/proxy/proxy_server.h"
27 #include "net/spdy/chromium/spdy_session.h" 27 #include "net/spdy/chromium/spdy_session.h"
28 #include "url/url_constants.h" 28 #include "url/url_constants.h"
29 29
30 namespace net { 30 namespace net {
31 31
32 namespace {
33
34 // Returns parameters associated with the proxy resolution.
35 std::unique_ptr<base::Value> NetLogHttpStreamJobProxyServerResolved(
36 const ProxyServer& proxy_server,
37 NetLogCaptureMode /* capture_mode */) {
38 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
39
40 dict->SetString("proxy_server", proxy_server.is_valid()
41 ? proxy_server.ToPacString()
42 : std::string());
43 return std::move(dict);
44 }
45
46 } // namespace
47
32 // The maximum time to wait for the alternate job to complete before resuming 48 // The maximum time to wait for the alternate job to complete before resuming
33 // the main job. 49 // the main job.
34 const int kMaxDelayTimeForMainJobSecs = 3; 50 const int kMaxDelayTimeForMainJobSecs = 3;
35 51
36 std::unique_ptr<base::Value> NetLogJobControllerCallback( 52 std::unique_ptr<base::Value> NetLogJobControllerCallback(
37 const GURL* url, 53 const GURL* url,
38 bool is_preconnect, 54 bool is_preconnect,
39 NetLogCaptureMode /* capture_mode */) { 55 NetLogCaptureMode /* capture_mode */) {
40 auto dict = base::MakeUnique<base::DictionaryValue>(); 56 auto dict = base::MakeUnique<base::DictionaryValue>();
41 dict->SetString("url", url->possibly_invalid_spec()); 57 dict->SetString("url", url->possibly_invalid_spec());
42 dict->SetBoolean("is_preconnect", is_preconnect); 58 dict->SetBoolean("is_preconnect", is_preconnect);
43 return std::move(dict); 59 return std::move(dict);
44 } 60 }
45 61
46 HttpStreamFactoryImpl::JobController::JobController( 62 HttpStreamFactoryImpl::JobController::JobController(
47 HttpStreamFactoryImpl* factory, 63 HttpStreamFactoryImpl* factory,
48 HttpStreamRequest::Delegate* delegate, 64 HttpStreamRequest::Delegate* delegate,
49 HttpNetworkSession* session, 65 HttpNetworkSession* session,
50 JobFactory* job_factory, 66 JobFactory* job_factory,
51 const HttpRequestInfo& request_info, 67 const HttpRequestInfo& request_info,
52 bool is_preconnect, 68 bool is_preconnect,
53 bool enable_ip_based_pooling, 69 bool enable_ip_based_pooling,
54 bool enable_alternative_services) 70 bool enable_alternative_services,
71 const SSLConfig& server_ssl_config,
72 const SSLConfig& proxy_ssl_config)
55 : factory_(factory), 73 : factory_(factory),
56 session_(session), 74 session_(session),
57 job_factory_(job_factory), 75 job_factory_(job_factory),
58 request_(nullptr), 76 request_(nullptr),
59 delegate_(delegate), 77 delegate_(delegate),
60 is_preconnect_(is_preconnect), 78 is_preconnect_(is_preconnect),
61 enable_ip_based_pooling_(enable_ip_based_pooling), 79 enable_ip_based_pooling_(enable_ip_based_pooling),
62 enable_alternative_services_(enable_alternative_services), 80 enable_alternative_services_(enable_alternative_services),
63 alternative_job_net_error_(OK), 81 alternative_job_net_error_(OK),
64 job_bound_(false), 82 job_bound_(false),
65 main_job_is_blocked_(false), 83 main_job_is_blocked_(false),
66 main_job_is_resumed_(false), 84 main_job_is_resumed_(false),
67 bound_job_(nullptr), 85 bound_job_(nullptr),
68 can_start_alternative_proxy_job_(false), 86 can_start_alternative_proxy_job_(true),
69 privacy_mode_(PRIVACY_MODE_DISABLED), 87 privacy_mode_(PRIVACY_MODE_DISABLED),
88 next_state_(STATE_RESOLVE_PROXY),
89 pac_request_(nullptr),
90 io_callback_(
91 base::Bind(&JobController::OnIOComplete, base::Unretained(this))),
92 request_info_(request_info),
93 server_ssl_config_(server_ssl_config),
94 proxy_ssl_config_(proxy_ssl_config),
95 num_streams_(0),
96 priority_(IDLE),
70 net_log_( 97 net_log_(
71 NetLogWithSource::Make(session->net_log(), 98 NetLogWithSource::Make(session->net_log(),
72 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), 99 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)),
73 ptr_factory_(this) { 100 ptr_factory_(this) {
74 DCHECK(factory); 101 DCHECK(factory);
75 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, 102 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER,
76 base::Bind(&NetLogJobControllerCallback, 103 base::Bind(&NetLogJobControllerCallback,
77 &request_info.url, is_preconnect)); 104 &request_info.url, is_preconnect));
78 } 105 }
79 106
80 HttpStreamFactoryImpl::JobController::~JobController() { 107 HttpStreamFactoryImpl::JobController::~JobController() {
81 main_job_.reset(); 108 main_job_.reset();
82 alternative_job_.reset(); 109 alternative_job_.reset();
83 bound_job_ = nullptr; 110 bound_job_ = nullptr;
111 if (pac_request_)
112 session_->proxy_service()->CancelPacRequest(pac_request_);
84 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); 113 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER);
85 } 114 }
86 115
87 bool HttpStreamFactoryImpl::JobController::for_websockets() { 116 bool HttpStreamFactoryImpl::JobController::for_websockets() {
88 return factory_->for_websockets_; 117 return factory_->for_websockets_;
89 } 118 }
90 119
91 HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start( 120 HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start(
92 const HttpRequestInfo& request_info,
93 HttpStreamRequest::Delegate* delegate, 121 HttpStreamRequest::Delegate* delegate,
94 WebSocketHandshakeStreamBase::CreateHelper* 122 WebSocketHandshakeStreamBase::CreateHelper*
95 websocket_handshake_stream_create_helper, 123 websocket_handshake_stream_create_helper,
96 const NetLogWithSource& source_net_log, 124 const NetLogWithSource& source_net_log,
97 HttpStreamRequest::StreamType stream_type, 125 HttpStreamRequest::StreamType stream_type,
98 RequestPriority priority, 126 RequestPriority priority) {
99 const SSLConfig& server_ssl_config,
100 const SSLConfig& proxy_ssl_config) {
101 DCHECK(factory_); 127 DCHECK(factory_);
102 DCHECK(!request_); 128 DCHECK(!request_);
103 129
104 privacy_mode_ = request_info.privacy_mode; 130 privacy_mode_ = request_info_.privacy_mode;
131 stream_type_ = stream_type;
132 priority_ = priority;
105 133
106 request_ = new Request(request_info.url, this, delegate, 134 request_ = new Request(request_info_.url, this, delegate,
107 websocket_handshake_stream_create_helper, 135 websocket_handshake_stream_create_helper,
108 source_net_log, stream_type); 136 source_net_log, stream_type);
109 // Associates |net_log_| with |source_net_log|. 137 // Associates |net_log_| with |source_net_log|.
110 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, 138 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND,
111 net_log_.source().ToEventParametersCallback()); 139 net_log_.source().ToEventParametersCallback());
112 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, 140 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND,
113 source_net_log.source().ToEventParametersCallback()); 141 source_net_log.source().ToEventParametersCallback());
114 142
115 CreateJobs(request_info, priority, server_ssl_config, proxy_ssl_config, 143 RunLoop(OK);
116 delegate, stream_type);
117
118 return request_; 144 return request_;
119 } 145 }
120 146
121 void HttpStreamFactoryImpl::JobController::Preconnect( 147 void HttpStreamFactoryImpl::JobController::Preconnect(int num_streams) {
122 int num_streams,
123 const HttpRequestInfo& request_info,
124 const SSLConfig& server_ssl_config,
125 const SSLConfig& proxy_ssl_config) {
126 DCHECK(!main_job_); 148 DCHECK(!main_job_);
127 DCHECK(!alternative_job_); 149 DCHECK(!alternative_job_);
128 DCHECK(is_preconnect_); 150 DCHECK(is_preconnect_);
129 151
130 privacy_mode_ = request_info.privacy_mode; 152 privacy_mode_ = request_info_.privacy_mode;
153 num_streams_ = num_streams;
131 154
132 HostPortPair destination(HostPortPair::FromURL(request_info.url)); 155 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
133 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); 156 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
134 157
135 const AlternativeService alternative_service = GetAlternativeServiceFor( 158 const AlternativeService alternative_service = GetAlternativeServiceFor(
136 request_info, nullptr, HttpStreamRequest::HTTP_STREAM); 159 request_info_, nullptr, HttpStreamRequest::HTTP_STREAM);
137 160
138 if (alternative_service.protocol != kProtoUnknown) { 161 if (alternative_service.protocol != kProtoUnknown) {
139 destination = alternative_service.host_port_pair(); 162 destination = alternative_service.host_port_pair();
140 ignore_result(ApplyHostMappingRules(request_info.url, &destination)); 163 ignore_result(ApplyHostMappingRules(request_info_.url, &destination));
141 } 164 }
142 165 RunLoop(OK);
143 // Due to how the socket pools handle priorities and idle sockets, only IDLE
144 // priority currently makes sense for preconnects. The priority for
145 // preconnects is currently ignored (see RequestSocketsForPool()), but could
146 // be used at some point for proxy resolution or something.
147 main_job_.reset(job_factory_->CreateJob(
148 this, PRECONNECT, session_, request_info, IDLE, server_ssl_config,
149 proxy_ssl_config, destination, origin_url, alternative_service,
150 enable_ip_based_pooling_, session_->net_log()));
151 main_job_->Preconnect(num_streams);
152 } 166 }
153 167
154 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { 168 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const {
155 DCHECK(request_); 169 DCHECK(request_);
170 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE)
171 return session_->proxy_service()->GetLoadState(pac_request_);
156 DCHECK(main_job_ || alternative_job_); 172 DCHECK(main_job_ || alternative_job_);
157 if (bound_job_) 173 if (bound_job_)
158 return bound_job_->GetLoadState(); 174 return bound_job_->GetLoadState();
159 175
160 // Just pick the first one. 176 // Just pick the first one.
161 return main_job_ ? main_job_->GetLoadState() 177 return main_job_ ? main_job_->GetLoadState()
162 : alternative_job_->GetLoadState(); 178 : alternative_job_->GetLoadState();
163 } 179 }
164 180
165 void HttpStreamFactoryImpl::JobController::OnRequestComplete() { 181 void HttpStreamFactoryImpl::JobController::OnRequestComplete() {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, 286 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info,
271 stream); 287 stream);
272 } 288 }
273 289
274 void HttpStreamFactoryImpl::JobController::OnStreamFailed( 290 void HttpStreamFactoryImpl::JobController::OnStreamFailed(
275 Job* job, 291 Job* job,
276 int status, 292 int status,
277 const SSLConfig& used_ssl_config) { 293 const SSLConfig& used_ssl_config) {
278 if (job->job_type() == ALTERNATIVE) { 294 if (job->job_type() == ALTERNATIVE) {
279 DCHECK_EQ(alternative_job_.get(), job); 295 DCHECK_EQ(alternative_job_.get(), job);
280 OnAlternativeJobFailed(status); 296 if (alternative_job_->alternative_proxy_server().is_valid()) {
297 OnAlternativeProxyJobFailed(status);
298 } else {
299 OnAlternativeServiceJobFailed(status);
300 }
281 } 301 }
282 302
283 MaybeResumeMainJob(job, base::TimeDelta()); 303 MaybeResumeMainJob(job, base::TimeDelta());
284 304
285 if (IsJobOrphaned(job)) { 305 if (IsJobOrphaned(job)) {
286 // We have bound a job to the associated Request, |job| has been orphaned. 306 // We have bound a job to the associated Request, |job| has been orphaned.
287 OnOrphanedJobComplete(job); 307 OnOrphanedJobComplete(job);
288 return; 308 return;
289 } 309 }
290 310
(...skipping 11 matching lines...) Expand all
302 } else { 322 } else {
303 DCHECK(job->job_type() == ALTERNATIVE); 323 DCHECK(job->job_type() == ALTERNATIVE);
304 alternative_job_.reset(); 324 alternative_job_.reset();
305 } 325 }
306 return; 326 return;
307 } else { 327 } else {
308 BindJob(job); 328 BindJob(job);
309 } 329 }
310 } 330 }
311 331
332 status = ReconsiderProxyAfterError(job, status);
333 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) {
334 RunLoop(OK);
335 return;
336 }
312 request_->OnStreamFailed(status, used_ssl_config); 337 request_->OnStreamFailed(status, used_ssl_config);
313 } 338 }
314 339
315 void HttpStreamFactoryImpl::JobController::OnCertificateError( 340 void HttpStreamFactoryImpl::JobController::OnCertificateError(
316 Job* job, 341 Job* job,
317 int status, 342 int status,
318 const SSLConfig& used_ssl_config, 343 const SSLConfig& used_ssl_config,
319 const SSLInfo& ssl_info) { 344 const SSLInfo& ssl_info) {
320 MaybeResumeMainJob(job, base::TimeDelta()); 345 MaybeResumeMainJob(job, base::TimeDelta());
321 346
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 BindJob(job); 420 BindJob(job);
396 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, 421 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info,
397 auth_controller); 422 auth_controller);
398 } 423 }
399 424
400 bool HttpStreamFactoryImpl::JobController::OnInitConnection( 425 bool HttpStreamFactoryImpl::JobController::OnInitConnection(
401 const ProxyInfo& proxy_info) { 426 const ProxyInfo& proxy_info) {
402 return factory_->OnInitConnection(*this, proxy_info, privacy_mode_); 427 return factory_->OnInitConnection(*this, proxy_info, privacy_mode_);
403 } 428 }
404 429
405 void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete(
406 Job* job,
407 const HttpRequestInfo& request_info,
408 RequestPriority priority,
409 const SSLConfig& server_ssl_config,
410 const SSLConfig& proxy_ssl_config,
411 HttpStreamRequest::StreamType stream_type) {
412 DCHECK(job);
413
414 ProxyServer alternative_proxy_server;
415 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(),
416 request_info.url,
417 &alternative_proxy_server)) {
418 return;
419 }
420
421 DCHECK(main_job_);
422 DCHECK_EQ(MAIN, job->job_type());
423 DCHECK(!alternative_job_);
424 DCHECK(!main_job_is_blocked_);
425
426 HostPortPair destination(HostPortPair::FromURL(request_info.url));
427 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
428
429 alternative_job_.reset(job_factory_->CreateJob(
430 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config,
431 proxy_ssl_config, destination, origin_url, alternative_proxy_server,
432 enable_ip_based_pooling_, job->net_log().net_log()));
433
434 can_start_alternative_proxy_job_ = false;
435 main_job_is_blocked_ = true;
436
437 base::ThreadTaskRunnerHandle::Get()->PostTask(
438 FROM_HERE,
439 base::Bind(
440 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob,
441 ptr_factory_.GetWeakPtr()));
442 }
443
444 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( 430 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
445 Job* job, 431 Job* job,
446 const base::WeakPtr<SpdySession>& spdy_session, 432 const base::WeakPtr<SpdySession>& spdy_session,
447 bool direct) { 433 bool direct) {
448 DCHECK(job); 434 DCHECK(job);
449 DCHECK(job->using_spdy()); 435 DCHECK(job->using_spdy());
450 DCHECK(!is_preconnect_); 436 DCHECK(!is_preconnect_);
451 437
452 bool is_job_orphaned = IsJobOrphaned(job); 438 bool is_job_orphaned = IsJobOrphaned(job);
453 439
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 return base::trace_event::EstimateMemoryUsage(main_job_) + 668 return base::trace_event::EstimateMemoryUsage(main_job_) +
683 base::trace_event::EstimateMemoryUsage(alternative_job_); 669 base::trace_event::EstimateMemoryUsage(alternative_job_);
684 } 670 }
685 671
686 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: 672 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl::
687 JobController::websocket_handshake_stream_create_helper() { 673 JobController::websocket_handshake_stream_create_helper() {
688 DCHECK(request_); 674 DCHECK(request_);
689 return request_->websocket_handshake_stream_create_helper(); 675 return request_->websocket_handshake_stream_create_helper();
690 } 676 }
691 677
692 void HttpStreamFactoryImpl::JobController::CreateJobs( 678 void HttpStreamFactoryImpl::JobController::OnIOComplete(int result) {
693 const HttpRequestInfo& request_info, 679 RunLoop(result);
694 RequestPriority priority, 680 }
695 const SSLConfig& server_ssl_config, 681
696 const SSLConfig& proxy_ssl_config, 682 void HttpStreamFactoryImpl::JobController::RunLoop(int result) {
697 HttpStreamRequest::Delegate* delegate, 683 int rv = DoLoop(result);
698 HttpStreamRequest::StreamType stream_type) { 684 if (rv == ERR_IO_PENDING)
685 return;
686 if (rv != OK) {
687 DCHECK(!main_job_);
688 DCHECK(!alternative_job_);
Zhongyi Shi 2017/05/10 20:28:16 Could you add some comments here? I think this i
xunjieli 2017/05/10 23:24:41 Done.
689
690 if (!request_)
691 return;
692 request_->OnStreamFailed(rv, server_ssl_config_);
693 }
694 }
695
696 int HttpStreamFactoryImpl::JobController::DoLoop(int rv) {
697 DCHECK_NE(next_state_, STATE_NONE);
698 do {
699 State state = next_state_;
700 next_state_ = STATE_NONE;
701 switch (state) {
702 case STATE_RESOLVE_PROXY:
703 DCHECK_EQ(OK, rv);
704 rv = DoResolveProxy();
705 break;
706 case STATE_RESOLVE_PROXY_COMPLETE:
707 rv = DoResolveProxyComplete(rv);
708 break;
709 case STATE_CREATE_JOBS:
710 DCHECK_EQ(OK, rv);
711 rv = DoCreateJobs();
712 break;
713 default:
714 NOTREACHED() << "bad state";
715 break;
716 }
717 } while (next_state_ != STATE_NONE && rv != ERR_IO_PENDING);
718 return rv;
719 }
720
721 int HttpStreamFactoryImpl::JobController::DoResolveProxy() {
722 DCHECK(!pac_request_);
723 DCHECK(session_);
724
725 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
726
727 if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
728 proxy_info_.UseDirect();
729 return OK;
730 }
731
732 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
733 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
734
735 return session_->proxy_service()->ResolveProxy(
736 origin_url, request_info_.method, &proxy_info_, io_callback_,
737 &pac_request_, session_->params().proxy_delegate, net_log_);
738 }
739
740 int HttpStreamFactoryImpl::JobController::DoResolveProxyComplete(int rv) {
741 DCHECK_NE(ERR_IO_PENDING, rv);
742
743 pac_request_ = nullptr;
744 net_log_.AddEvent(
745 NetLogEventType::HTTP_STREAM_JOB_PROXY_SERVER_RESOLVED,
746 base::Bind(
747 &NetLogHttpStreamJobProxyServerResolved,
748 proxy_info_.is_empty() ? ProxyServer() : proxy_info_.proxy_server()));
749
750 if (rv == OK)
751 next_state_ = STATE_CREATE_JOBS;
752 return rv;
753 }
754
755 int HttpStreamFactoryImpl::JobController::DoCreateJobs() {
699 DCHECK(!main_job_); 756 DCHECK(!main_job_);
700 DCHECK(!alternative_job_); 757 DCHECK(!alternative_job_);
701 HostPortPair destination(HostPortPair::FromURL(request_info.url));
702 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
703 758
704 main_job_.reset(job_factory_->CreateJob( 759 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
705 this, MAIN, session_, request_info, priority, server_ssl_config, 760 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
706 proxy_ssl_config, destination, origin_url, enable_ip_based_pooling_,
707 net_log_.net_log()));
708 761
709 // Create an alternative job if alternative service is set up for this domain. 762 // Create an alternative job if alternative service is set up for this domain.
710 const AlternativeService alternative_service = 763 const AlternativeService alternative_service =
711 GetAlternativeServiceFor(request_info, delegate, stream_type); 764 GetAlternativeServiceFor(request_info_, delegate_, stream_type_);
712 765
766 // Remove unsupported proxies from the list. ProxyServer::SCHEME_QUIC is not
767 // yet supported.
768 int supported_proxies = ProxyServer::SCHEME_DIRECT |
769 ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
770 ProxyServer::SCHEME_SOCKS4 |
771 ProxyServer::SCHEME_SOCKS5;
772
773 if (session_->IsQuicEnabled())
774 supported_proxies |= ProxyServer::SCHEME_QUIC;
775 proxy_info_.RemoveProxiesWithoutScheme(supported_proxies);
Zhongyi Shi 2017/05/10 20:28:16 optional nit: this is trying to clean up proxies f
xunjieli 2017/05/10 23:24:41 Done.
776
Zhongyi Shi 2017/05/10 20:28:16 Also, we used to check the proxy_info list is non-
777 if (is_preconnect_) {
778 // Due to how the socket pools handle priorities and idle sockets, only IDLE
779 // priority currently makes sense for preconnects. The priority for
780 // preconnects is currently ignored (see RequestSocketsForPool()), but could
781 // be used at some point for proxy resolution or something.
782 main_job_.reset(job_factory_->CreateAltJob(
Zhongyi Shi 2017/05/10 20:28:16 Hrm, that suggests s/CreateAltJob/CreateAltSvcJob,
xunjieli 2017/05/10 23:24:41 Done.
783 this, PRECONNECT, session_, request_info_, IDLE, proxy_info_,
784 server_ssl_config_, proxy_ssl_config_, destination, origin_url,
785 alternative_service, enable_ip_based_pooling_, session_->net_log()));
786 main_job_->Preconnect(num_streams_);
787 return OK;
788 }
789 main_job_.reset(job_factory_->CreateMainJob(
790 this, MAIN, session_, request_info_, priority_, proxy_info_,
791 server_ssl_config_, proxy_ssl_config_, destination, origin_url,
792 enable_ip_based_pooling_, net_log_.net_log()));
793 // AltSvc can only be set for HTTPS requests while Alternative Proxy is set
794 // for HTTP requests.
713 if (alternative_service.protocol != kProtoUnknown) { 795 if (alternative_service.protocol != kProtoUnknown) {
714 // Never share connection with other jobs for FTP requests. 796 // Never share connection with other jobs for FTP requests.
715 DVLOG(1) << "Selected alternative service (host: " 797 DVLOG(1) << "Selected alternative service (host: "
716 << alternative_service.host_port_pair().host() 798 << alternative_service.host_port_pair().host()
717 << " port: " << alternative_service.host_port_pair().port() << ")"; 799 << " port: " << alternative_service.host_port_pair().port() << ")";
718 800
719 DCHECK(!request_info.url.SchemeIs(url::kFtpScheme)); 801 DCHECK(!request_info_.url.SchemeIs(url::kFtpScheme));
720 HostPortPair alternative_destination(alternative_service.host_port_pair()); 802 HostPortPair alternative_destination(alternative_service.host_port_pair());
721 ignore_result( 803 ignore_result(
722 ApplyHostMappingRules(request_info.url, &alternative_destination)); 804 ApplyHostMappingRules(request_info_.url, &alternative_destination));
723 805
724 alternative_job_.reset(job_factory_->CreateJob( 806 alternative_job_.reset(job_factory_->CreateAltJob(
725 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, 807 this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_,
726 proxy_ssl_config, alternative_destination, origin_url, 808 server_ssl_config_, proxy_ssl_config_, alternative_destination,
727 alternative_service, enable_ip_based_pooling_, net_log_.net_log())); 809 origin_url, alternative_service, enable_ip_based_pooling_,
810 net_log_.net_log()));
728 811
729 main_job_is_blocked_ = true; 812 main_job_is_blocked_ = true;
730 alternative_job_->Start(request_->stream_type()); 813 alternative_job_->Start(request_->stream_type());
731 } else { 814 } else {
732 can_start_alternative_proxy_job_ = true; 815 ProxyServer alternative_proxy_server;
816 if (ShouldCreateAlternativeProxyServerJob(proxy_info_, request_info_.url,
817 &alternative_proxy_server)) {
818 DCHECK(!main_job_is_blocked_);
819 ProxyInfo alternative_proxy_info;
820 alternative_proxy_info.UseProxyServer(alternative_proxy_server);
821
822 alternative_job_.reset(job_factory_->CreateAltProxyJob(
823 this, ALTERNATIVE, session_, request_info_, priority_,
824 alternative_proxy_info, server_ssl_config_, proxy_ssl_config_,
825 destination, origin_url, alternative_proxy_server,
826 enable_ip_based_pooling_, net_log_.net_log()));
827
828 can_start_alternative_proxy_job_ = false;
829 main_job_is_blocked_ = true;
830 alternative_job_->Start(request_->stream_type());
Zhongyi Shi 2017/05/10 20:28:15 Woohoo! This is much cleaner!
831 }
733 } 832 }
734 // Even if |alternative_job| has already finished, it will not have notified 833 // Even if |alternative_job| has already finished, it will not have notified
735 // the request yet, since we defer that to the next iteration of the 834 // the request yet, since we defer that to the next iteration of the
736 // MessageLoop, so starting |main_job_| is always safe. 835 // MessageLoop, so starting |main_job_| is always safe.
737 main_job_->Start(request_->stream_type()); 836 main_job_->Start(request_->stream_type());
837 return OK;
738 } 838 }
739 839
740 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { 840 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) {
741 DCHECK(request_); 841 DCHECK(request_);
742 DCHECK(job); 842 DCHECK(job);
743 DCHECK(job == alternative_job_.get() || job == main_job_.get()); 843 DCHECK(job == alternative_job_.get() || job == main_job_.get());
744 DCHECK(!job_bound_); 844 DCHECK(!job_bound_);
745 DCHECK(!bound_job_); 845 DCHECK(!bound_job_);
746 846
747 job_bound_ = true; 847 job_bound_ = true;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 } 923 }
824 924
825 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( 925 void HttpStreamFactoryImpl::JobController::MarkRequestComplete(
826 bool was_alpn_negotiated, 926 bool was_alpn_negotiated,
827 NextProto negotiated_protocol, 927 NextProto negotiated_protocol,
828 bool using_spdy) { 928 bool using_spdy) {
829 if (request_) 929 if (request_)
830 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy); 930 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy);
831 } 931 }
832 932
833 void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed( 933 void HttpStreamFactoryImpl::JobController::OnAlternativeServiceJobFailed(
834 int net_error) { 934 int net_error) {
835 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); 935 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE);
836 DCHECK_NE(OK, net_error); 936 DCHECK_NE(OK, net_error);
937 DCHECK_NE(kProtoUnknown, alternative_job_->alternative_service().protocol);
837 938
838 alternative_job_net_error_ = net_error; 939 alternative_job_net_error_ = net_error;
839 940 failed_alternative_service_ = alternative_job_->alternative_service();
840 if (alternative_job_->alternative_proxy_server().is_valid()) {
841 failed_alternative_proxy_server_ =
842 alternative_job_->alternative_proxy_server();
843 } else {
844 DCHECK(!failed_alternative_proxy_server_.is_valid());
845 failed_alternative_service_ = alternative_job_->alternative_service();
846 }
847 941
848 if (IsJobOrphaned(alternative_job_.get())) { 942 if (IsJobOrphaned(alternative_job_.get())) {
849 // If |request_| is gone then it must have been successfully served by 943 // If |request_| is gone then it must have been successfully served by
850 // |main_job_|. 944 // |main_job_|.
851 // If |request_| is bound to a different job, then it is being 945 // If |request_| is bound to a different job, then it is being
852 // successfully serverd by the main job. 946 // successfully serverd by the main job.
853 ReportBrokenAlternativeService(); 947 ReportBrokenAlternativeService();
854 } 948 }
855 } 949 }
856 950
951 void HttpStreamFactoryImpl::JobController::OnAlternativeProxyJobFailed(
952 int net_error) {
953 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE);
954 DCHECK_NE(OK, net_error);
955 DCHECK(alternative_job_->alternative_proxy_server().is_valid());
956
957 // Need to mark alt proxy as broken regardless whether the job is bound.
958 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
959 if (proxy_delegate) {
960 proxy_delegate->OnAlternativeProxyBroken(
961 alternative_job_->alternative_proxy_server());
962 }
963 }
964
857 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { 965 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() {
858 DCHECK(failed_alternative_service_.protocol != kProtoUnknown || 966 DCHECK(failed_alternative_service_.protocol != kProtoUnknown);
859 failed_alternative_proxy_server_.is_valid());
860 DCHECK_NE(OK, alternative_job_net_error_); 967 DCHECK_NE(OK, alternative_job_net_error_);
861 968
862 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", 969 int error_to_report = alternative_job_net_error_;
863 -alternative_job_net_error_); 970 alternative_job_net_error_ = OK;
971 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", -error_to_report);
864 972
865 if (session_->params().quic_do_not_mark_as_broken_on_network_change && 973 if (session_->params().quic_do_not_mark_as_broken_on_network_change &&
866 (alternative_job_net_error_ == ERR_NETWORK_CHANGED || 974 (error_to_report == ERR_NETWORK_CHANGED ||
867 alternative_job_net_error_ == ERR_INTERNET_DISCONNECTED)) { 975 error_to_report == ERR_INTERNET_DISCONNECTED)) {
868 // No need to mark alternative service or proxy as broken. 976 // No need to mark alternative service or proxy as broken.
869 return; 977 return;
870 } 978 }
871 979
872 if (failed_alternative_proxy_server_.is_valid()) { 980 HistogramBrokenAlternateProtocolLocation(
873 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; 981 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
874 if (proxy_delegate) { 982 session_->http_server_properties()->MarkAlternativeServiceBroken(
875 proxy_delegate->OnAlternativeProxyBroken( 983 failed_alternative_service_);
876 failed_alternative_proxy_server_);
877 }
878 } else {
879 HistogramBrokenAlternateProtocolLocation(
880 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
881 session_->http_server_properties()->MarkAlternativeServiceBroken(
882 failed_alternative_service_);
883 }
884 } 984 }
885 985
886 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { 986 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() {
887 if (!request_ && !main_job_ && !alternative_job_) { 987 if (!request_ && !main_job_ && !alternative_job_) {
888 DCHECK(!bound_job_); 988 DCHECK(!bound_job_);
889 factory_->OnJobControllerComplete(this); 989 factory_->OnJobControllerComplete(this);
890 } 990 }
891 } 991 }
892 992
893 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( 993 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules(
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 1126
1027 // Ask delegate to mark QUIC as broken for the origin. 1127 // Ask delegate to mark QUIC as broken for the origin.
1028 if (quic_advertised && quic_all_broken && delegate != nullptr) 1128 if (quic_advertised && quic_all_broken && delegate != nullptr)
1029 delegate->OnQuicBroken(); 1129 delegate->OnQuicBroken();
1030 1130
1031 return first_alternative_service; 1131 return first_alternative_service;
1032 } 1132 }
1033 1133
1034 bool HttpStreamFactoryImpl::JobController:: 1134 bool HttpStreamFactoryImpl::JobController::
1035 ShouldCreateAlternativeProxyServerJob( 1135 ShouldCreateAlternativeProxyServerJob(
1036 Job* job,
1037 const ProxyInfo& proxy_info, 1136 const ProxyInfo& proxy_info,
1038 const GURL& url, 1137 const GURL& url,
1039 ProxyServer* alternative_proxy_server) const { 1138 ProxyServer* alternative_proxy_server) const {
1040 DCHECK(!alternative_proxy_server->is_valid()); 1139 DCHECK(!alternative_proxy_server->is_valid());
1041 1140
1042 if (!enable_alternative_services_) 1141 if (!enable_alternative_services_)
1043 return false; 1142 return false;
1044 1143
1045 if (!can_start_alternative_proxy_job_) { 1144 if (!can_start_alternative_proxy_job_) {
1046 // Either an alternative service job or an alternative proxy server job has 1145 // Either an alternative service job or an alternative proxy server job has
1047 // already been started. 1146 // already been started.
1048 return false; 1147 return false;
1049 } 1148 }
1050 1149
1051 if (job->job_type() == ALTERNATIVE) {
1052 // If |job| is using alternative service, then alternative proxy server
1053 // should not be used.
1054 return false;
1055 }
1056
1057 if (is_preconnect_ || job->job_type() == PRECONNECT) {
1058 // Preconnects should be fetched using only the main job to keep the
1059 // resource utilization down.
1060 return false;
1061 }
1062
1063 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { 1150 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) {
1064 // Alternative proxy server job can be created only if |job| fetches the 1151 // Alternative proxy server job can be created only if |job| fetches the
1065 // |request_| through a non-QUIC proxy. 1152 // |request_| through a non-QUIC proxy.
1066 return false; 1153 return false;
1067 } 1154 }
1068 1155
1069 if (!url.SchemeIs(url::kHttpScheme)) { 1156 if (!url.SchemeIs(url::kHttpScheme)) {
1070 // Only HTTP URLs can be fetched through alternative proxy server, since the 1157 // Only HTTP URLs can be fetched through alternative proxy server, since the
1071 // alternative proxy server may not support fetching of URLs with other 1158 // alternative proxy server may not support fetching of URLs with other
1072 // schemes. 1159 // schemes.
1073 return false; 1160 return false;
1074 } 1161 }
1075 1162
1076 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; 1163 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
1077 if (!proxy_delegate) 1164 if (!proxy_delegate)
1078 return false; 1165 return false;
1079
1080 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), 1166 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(),
1081 alternative_proxy_server); 1167 alternative_proxy_server);
1082 1168
1083 if (!alternative_proxy_server->is_valid()) 1169 if (!alternative_proxy_server->is_valid())
1084 return false; 1170 return false;
1085 1171
1086 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server())); 1172 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server()));
1087 1173
1088 if (!alternative_proxy_server->is_https() && 1174 if (!alternative_proxy_server->is_https() &&
1089 !alternative_proxy_server->is_quic()) { 1175 !alternative_proxy_server->is_quic()) {
(...skipping 27 matching lines...) Expand all
1117 if (job->using_existing_quic_session()) { 1203 if (job->using_existing_quic_session()) {
1118 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, 1204 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE,
1119 proxy_server_used); 1205 proxy_server_used);
1120 return; 1206 return;
1121 } 1207 }
1122 1208
1123 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, 1209 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE,
1124 proxy_server_used); 1210 proxy_server_used);
1125 } 1211 }
1126 1212
1127 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() {
1128 if (!alternative_job_ || !request_)
1129 return;
1130 DCHECK(alternative_job_->alternative_proxy_server().is_valid());
1131 alternative_job_->Start(request_->stream_type());
1132 }
1133
1134 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { 1213 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const {
1135 return !request_ || (job_bound_ && bound_job_ != job); 1214 return !request_ || (job_bound_ && bound_job_ != job);
1136 } 1215 }
1137 1216
1217 int HttpStreamFactoryImpl::JobController::ReconsiderProxyAfterError(Job* job,
1218 int error) {
1219 DCHECK(!pac_request_);
1220 DCHECK(session_);
1221
1222 if (!job->should_reconsider_proxy())
1223 return error;
1224
1225 DCHECK(!job->alternative_proxy_server().is_valid());
1226
1227 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG.
1228 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG)
1229 return error;
1230
1231 if (request_info_.load_flags & LOAD_BYPASS_PROXY)
1232 return error;
1233
1234 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
1235 session_->ssl_client_auth_cache()->Remove(
1236 proxy_info_.proxy_server().host_port_pair());
1237 }
1238
1239 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1240 request_info_.url, request_info_.method, error, &proxy_info_,
1241 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_);
1242 if (rv == OK || rv == ERR_IO_PENDING) {
1243 RemoveRequestFromSpdySessionRequestMap();
1244 // Abandon all Jobs and start over.
1245 job_bound_ = false;
1246 bound_job_ = nullptr;
1247 alternative_job_.reset();
1248 main_job_.reset();
1249 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1250 } else {
1251 // If ReconsiderProxyAfterError() failed synchronously, it means
1252 // there was nothing left to fall-back to, so fail the transaction
1253 // with the last connection error we got.
1254 // TODO(eroman): This is a confusing contract, make it more obvious.
1255 rv = error;
1256 }
1257 return rv;
1258 }
1259
1138 } // namespace net 1260 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698