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

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: rebased 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 next_state_(STATE_RESOLVE_PROXY),
88 pac_request_(nullptr),
89 io_callback_(
90 base::Bind(&JobController::OnIOComplete, base::Unretained(this))),
91 request_info_(request_info),
92 server_ssl_config_(server_ssl_config),
93 proxy_ssl_config_(proxy_ssl_config),
94 num_streams_(0),
95 priority_(IDLE),
70 net_log_( 96 net_log_(
71 NetLogWithSource::Make(session->net_log(), 97 NetLogWithSource::Make(session->net_log(),
72 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), 98 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)),
73 ptr_factory_(this) { 99 ptr_factory_(this) {
74 DCHECK(factory); 100 DCHECK(factory);
75 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, 101 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER,
76 base::Bind(&NetLogJobControllerCallback, 102 base::Bind(&NetLogJobControllerCallback,
77 &request_info.url, is_preconnect)); 103 &request_info.url, is_preconnect));
78 } 104 }
79 105
80 HttpStreamFactoryImpl::JobController::~JobController() { 106 HttpStreamFactoryImpl::JobController::~JobController() {
81 main_job_.reset(); 107 main_job_.reset();
82 alternative_job_.reset(); 108 alternative_job_.reset();
83 bound_job_ = nullptr; 109 bound_job_ = nullptr;
110 if (pac_request_)
111 session_->proxy_service()->CancelPacRequest(pac_request_);
84 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); 112 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER);
85 } 113 }
86 114
87 bool HttpStreamFactoryImpl::JobController::for_websockets() { 115 bool HttpStreamFactoryImpl::JobController::for_websockets() {
88 return factory_->for_websockets_; 116 return factory_->for_websockets_;
89 } 117 }
90 118
91 HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start( 119 HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start(
92 const HttpRequestInfo& request_info,
93 HttpStreamRequest::Delegate* delegate, 120 HttpStreamRequest::Delegate* delegate,
94 WebSocketHandshakeStreamBase::CreateHelper* 121 WebSocketHandshakeStreamBase::CreateHelper*
95 websocket_handshake_stream_create_helper, 122 websocket_handshake_stream_create_helper,
96 const NetLogWithSource& source_net_log, 123 const NetLogWithSource& source_net_log,
97 HttpStreamRequest::StreamType stream_type, 124 HttpStreamRequest::StreamType stream_type,
98 RequestPriority priority, 125 RequestPriority priority) {
99 const SSLConfig& server_ssl_config,
100 const SSLConfig& proxy_ssl_config) {
101 DCHECK(factory_); 126 DCHECK(factory_);
102 DCHECK(!request_); 127 DCHECK(!request_);
103 128
104 privacy_mode_ = request_info.privacy_mode; 129 stream_type_ = stream_type;
130 priority_ = priority;
105 131
106 request_ = new Request(request_info.url, this, delegate, 132 request_ = new Request(request_info_.url, this, delegate,
107 websocket_handshake_stream_create_helper, 133 websocket_handshake_stream_create_helper,
108 source_net_log, stream_type); 134 source_net_log, stream_type);
109 // Associates |net_log_| with |source_net_log|. 135 // Associates |net_log_| with |source_net_log|.
110 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, 136 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND,
111 net_log_.source().ToEventParametersCallback()); 137 net_log_.source().ToEventParametersCallback());
112 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, 138 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND,
113 source_net_log.source().ToEventParametersCallback()); 139 source_net_log.source().ToEventParametersCallback());
114 140
115 CreateJobs(request_info, priority, server_ssl_config, proxy_ssl_config, 141 RunLoop(OK);
116 delegate, stream_type);
117
118 return request_; 142 return request_;
119 } 143 }
120 144
121 void HttpStreamFactoryImpl::JobController::Preconnect( 145 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_); 146 DCHECK(!main_job_);
127 DCHECK(!alternative_job_); 147 DCHECK(!alternative_job_);
128 DCHECK(is_preconnect_); 148 DCHECK(is_preconnect_);
129 149
130 privacy_mode_ = request_info.privacy_mode; 150 stream_type_ = HttpStreamRequest::HTTP_STREAM;
151 num_streams_ = num_streams;
131 152
132 HostPortPair destination(HostPortPair::FromURL(request_info.url)); 153 RunLoop(OK);
133 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
134
135 const AlternativeService alternative_service = GetAlternativeServiceFor(
136 request_info, nullptr, HttpStreamRequest::HTTP_STREAM);
137
138 if (alternative_service.protocol != kProtoUnknown) {
139 destination = alternative_service.host_port_pair();
140 ignore_result(ApplyHostMappingRules(request_info.url, &destination));
141 }
142
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 } 154 }
153 155
154 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { 156 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const {
155 DCHECK(request_); 157 DCHECK(request_);
158 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE)
159 return session_->proxy_service()->GetLoadState(pac_request_);
156 DCHECK(main_job_ || alternative_job_); 160 DCHECK(main_job_ || alternative_job_);
157 if (bound_job_) 161 if (bound_job_)
158 return bound_job_->GetLoadState(); 162 return bound_job_->GetLoadState();
159 163
160 // Just pick the first one. 164 // Just pick the first one.
161 return main_job_ ? main_job_->GetLoadState() 165 return main_job_ ? main_job_->GetLoadState()
162 : alternative_job_->GetLoadState(); 166 : alternative_job_->GetLoadState();
163 } 167 }
164 168
165 void HttpStreamFactoryImpl::JobController::OnRequestComplete() { 169 void HttpStreamFactoryImpl::JobController::OnRequestComplete() {
(...skipping 29 matching lines...) Expand all
195 if (alternative_job_) { 199 if (alternative_job_) {
196 alternative_job_->SetPriority(priority); 200 alternative_job_->SetPriority(priority);
197 } 201 }
198 } 202 }
199 203
200 void HttpStreamFactoryImpl::JobController::OnStreamReady( 204 void HttpStreamFactoryImpl::JobController::OnStreamReady(
201 Job* job, 205 Job* job,
202 const SSLConfig& used_ssl_config) { 206 const SSLConfig& used_ssl_config) {
203 DCHECK(job); 207 DCHECK(job);
204 208
205 factory_->OnStreamReady(job->proxy_info(), privacy_mode_); 209 factory_->OnStreamReady(job->proxy_info(), request_info_.privacy_mode);
206 210
207 if (IsJobOrphaned(job)) { 211 if (IsJobOrphaned(job)) {
208 // We have bound a job to the associated Request, |job| has been orphaned. 212 // We have bound a job to the associated Request, |job| has been orphaned.
209 OnOrphanedJobComplete(job); 213 OnOrphanedJobComplete(job);
210 return; 214 return;
211 } 215 }
212 std::unique_ptr<HttpStream> stream = job->ReleaseStream(); 216 std::unique_ptr<HttpStream> stream = job->ReleaseStream();
213 DCHECK(stream); 217 DCHECK(stream);
214 218
215 MarkRequestComplete(job->was_alpn_negotiated(), job->negotiated_protocol(), 219 MarkRequestComplete(job->was_alpn_negotiated(), job->negotiated_protocol(),
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, 274 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info,
271 stream); 275 stream);
272 } 276 }
273 277
274 void HttpStreamFactoryImpl::JobController::OnStreamFailed( 278 void HttpStreamFactoryImpl::JobController::OnStreamFailed(
275 Job* job, 279 Job* job,
276 int status, 280 int status,
277 const SSLConfig& used_ssl_config) { 281 const SSLConfig& used_ssl_config) {
278 if (job->job_type() == ALTERNATIVE) { 282 if (job->job_type() == ALTERNATIVE) {
279 DCHECK_EQ(alternative_job_.get(), job); 283 DCHECK_EQ(alternative_job_.get(), job);
280 OnAlternativeJobFailed(status); 284 if (alternative_job_->alternative_proxy_server().is_valid()) {
285 OnAlternativeProxyJobFailed(status);
286 } else {
287 OnAlternativeServiceJobFailed(status);
288 }
281 } 289 }
282 290
283 MaybeResumeMainJob(job, base::TimeDelta()); 291 MaybeResumeMainJob(job, base::TimeDelta());
284 292
285 if (IsJobOrphaned(job)) { 293 if (IsJobOrphaned(job)) {
286 // We have bound a job to the associated Request, |job| has been orphaned. 294 // We have bound a job to the associated Request, |job| has been orphaned.
287 OnOrphanedJobComplete(job); 295 OnOrphanedJobComplete(job);
288 return; 296 return;
289 } 297 }
290 298
(...skipping 11 matching lines...) Expand all
302 } else { 310 } else {
303 DCHECK(job->job_type() == ALTERNATIVE); 311 DCHECK(job->job_type() == ALTERNATIVE);
304 alternative_job_.reset(); 312 alternative_job_.reset();
305 } 313 }
306 return; 314 return;
307 } else { 315 } else {
308 BindJob(job); 316 BindJob(job);
309 } 317 }
310 } 318 }
311 319
320 status = ReconsiderProxyAfterError(job, status);
321 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) {
322 RunLoop(OK);
323 return;
324 }
312 request_->OnStreamFailed(status, used_ssl_config); 325 request_->OnStreamFailed(status, used_ssl_config);
313 } 326 }
314 327
315 void HttpStreamFactoryImpl::JobController::OnCertificateError( 328 void HttpStreamFactoryImpl::JobController::OnCertificateError(
316 Job* job, 329 Job* job,
317 int status, 330 int status,
318 const SSLConfig& used_ssl_config, 331 const SSLConfig& used_ssl_config,
319 const SSLInfo& ssl_info) { 332 const SSLInfo& ssl_info) {
320 MaybeResumeMainJob(job, base::TimeDelta()); 333 MaybeResumeMainJob(job, base::TimeDelta());
321 334
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 if (!request_) 405 if (!request_)
393 return; 406 return;
394 if (!bound_job_) 407 if (!bound_job_)
395 BindJob(job); 408 BindJob(job);
396 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, 409 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info,
397 auth_controller); 410 auth_controller);
398 } 411 }
399 412
400 bool HttpStreamFactoryImpl::JobController::OnInitConnection( 413 bool HttpStreamFactoryImpl::JobController::OnInitConnection(
401 const ProxyInfo& proxy_info) { 414 const ProxyInfo& proxy_info) {
402 return factory_->OnInitConnection(*this, proxy_info, privacy_mode_); 415 return factory_->OnInitConnection(*this, proxy_info,
403 } 416 request_info_.privacy_mode);
404
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 } 417 }
443 418
444 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( 419 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
445 Job* job, 420 Job* job,
446 const base::WeakPtr<SpdySession>& spdy_session, 421 const base::WeakPtr<SpdySession>& spdy_session,
447 bool direct) { 422 bool direct) {
448 DCHECK(job); 423 DCHECK(job);
449 DCHECK(job->using_spdy()); 424 DCHECK(job->using_spdy());
450 DCHECK(!is_preconnect_); 425 DCHECK(!is_preconnect_);
451 426
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 return base::trace_event::EstimateMemoryUsage(main_job_) + 657 return base::trace_event::EstimateMemoryUsage(main_job_) +
683 base::trace_event::EstimateMemoryUsage(alternative_job_); 658 base::trace_event::EstimateMemoryUsage(alternative_job_);
684 } 659 }
685 660
686 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: 661 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl::
687 JobController::websocket_handshake_stream_create_helper() { 662 JobController::websocket_handshake_stream_create_helper() {
688 DCHECK(request_); 663 DCHECK(request_);
689 return request_->websocket_handshake_stream_create_helper(); 664 return request_->websocket_handshake_stream_create_helper();
690 } 665 }
691 666
692 void HttpStreamFactoryImpl::JobController::CreateJobs( 667 void HttpStreamFactoryImpl::JobController::OnIOComplete(int result) {
693 const HttpRequestInfo& request_info, 668 RunLoop(result);
694 RequestPriority priority, 669 }
695 const SSLConfig& server_ssl_config, 670
696 const SSLConfig& proxy_ssl_config, 671 void HttpStreamFactoryImpl::JobController::RunLoop(int result) {
697 HttpStreamRequest::Delegate* delegate, 672 int rv = DoLoop(result);
698 HttpStreamRequest::StreamType stream_type) { 673 if (rv == ERR_IO_PENDING)
674 return;
675 if (rv != OK) {
676 // DoLoop can only fail during proxy resolution step which happens before
677 // any jobs are created. Notify |request_| of the failure one message loop
678 // iteration later to avoid re-entrancy.
679 DCHECK(!main_job_);
680 DCHECK(!alternative_job_);
681 base::ThreadTaskRunnerHandle::Get()->PostTask(
682 FROM_HERE,
683 base::Bind(&HttpStreamFactoryImpl::JobController::NotifyRequestFailed,
684 ptr_factory_.GetWeakPtr(), rv));
685 }
686 }
687
688 int HttpStreamFactoryImpl::JobController::DoLoop(int rv) {
689 DCHECK_NE(next_state_, STATE_NONE);
690 do {
691 State state = next_state_;
692 next_state_ = STATE_NONE;
693 switch (state) {
694 case STATE_RESOLVE_PROXY:
695 DCHECK_EQ(OK, rv);
696 rv = DoResolveProxy();
697 break;
698 case STATE_RESOLVE_PROXY_COMPLETE:
699 rv = DoResolveProxyComplete(rv);
700 break;
701 case STATE_CREATE_JOBS:
702 DCHECK_EQ(OK, rv);
703 rv = DoCreateJobs();
704 break;
705 default:
706 NOTREACHED() << "bad state";
707 break;
708 }
709 } while (next_state_ != STATE_NONE && rv != ERR_IO_PENDING);
710 return rv;
711 }
712
713 int HttpStreamFactoryImpl::JobController::DoResolveProxy() {
714 DCHECK(!pac_request_);
715 DCHECK(session_);
716
717 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
718
719 if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
720 proxy_info_.UseDirect();
721 return OK;
722 }
723
724 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
725 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
726
727 return session_->proxy_service()->ResolveProxy(
728 origin_url, request_info_.method, &proxy_info_, io_callback_,
729 &pac_request_, session_->params().proxy_delegate, net_log_);
730 }
731
732 int HttpStreamFactoryImpl::JobController::DoResolveProxyComplete(int rv) {
733 DCHECK_NE(ERR_IO_PENDING, rv);
734
735 pac_request_ = nullptr;
736 net_log_.AddEvent(
737 NetLogEventType::HTTP_STREAM_JOB_PROXY_SERVER_RESOLVED,
738 base::Bind(
739 &NetLogHttpStreamJobProxyServerResolved,
740 proxy_info_.is_empty() ? ProxyServer() : proxy_info_.proxy_server()));
741
742 if (rv != OK)
743 return rv;
744 // Remove unsupported proxies from the list.
745 int supported_proxies = ProxyServer::SCHEME_DIRECT |
746 ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
747 ProxyServer::SCHEME_SOCKS4 |
748 ProxyServer::SCHEME_SOCKS5;
749 if (session_->IsQuicEnabled())
750 supported_proxies |= ProxyServer::SCHEME_QUIC;
751 proxy_info_.RemoveProxiesWithoutScheme(supported_proxies);
752
753 if (proxy_info_.is_empty()) {
754 // No proxies/direct to choose from.
755 return ERR_NO_SUPPORTED_PROXIES;
756 }
757
758 next_state_ = STATE_CREATE_JOBS;
759 return rv;
760 }
761
762 int HttpStreamFactoryImpl::JobController::DoCreateJobs() {
699 DCHECK(!main_job_); 763 DCHECK(!main_job_);
700 DCHECK(!alternative_job_); 764 DCHECK(!alternative_job_);
701 HostPortPair destination(HostPortPair::FromURL(request_info.url));
702 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
703 765
704 main_job_.reset(job_factory_->CreateJob( 766 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
705 this, MAIN, session_, request_info, priority, server_ssl_config, 767 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 768
709 // Create an alternative job if alternative service is set up for this domain. 769 // Create an alternative job if alternative service is set up for this domain.
710 const AlternativeService alternative_service = 770 const AlternativeService alternative_service =
711 GetAlternativeServiceFor(request_info, delegate, stream_type); 771 GetAlternativeServiceFor(request_info_, delegate_, stream_type_);
712 772
773 if (is_preconnect_) {
774 // Due to how the socket pools handle priorities and idle sockets, only IDLE
775 // priority currently makes sense for preconnects. The priority for
776 // preconnects is currently ignored (see RequestSocketsForPool()), but could
777 // be used at some point for proxy resolution or something.
778 main_job_.reset(job_factory_->CreateAltSvcJob(
779 this, PRECONNECT, session_, request_info_, IDLE, proxy_info_,
780 server_ssl_config_, proxy_ssl_config_, destination, origin_url,
781 alternative_service, enable_ip_based_pooling_, session_->net_log()));
782 main_job_->Preconnect(num_streams_);
783 return OK;
784 }
785 main_job_.reset(job_factory_->CreateMainJob(
786 this, MAIN, session_, request_info_, priority_, proxy_info_,
787 server_ssl_config_, proxy_ssl_config_, destination, origin_url,
788 enable_ip_based_pooling_, net_log_.net_log()));
789 // Alternative Service can only be set for HTTPS requests while Alternative
790 // Proxy is set for HTTP requests.
713 if (alternative_service.protocol != kProtoUnknown) { 791 if (alternative_service.protocol != kProtoUnknown) {
714 // Never share connection with other jobs for FTP requests. 792 // Never share connection with other jobs for FTP requests.
715 DVLOG(1) << "Selected alternative service (host: " 793 DVLOG(1) << "Selected alternative service (host: "
716 << alternative_service.host_port_pair().host() 794 << alternative_service.host_port_pair().host()
717 << " port: " << alternative_service.host_port_pair().port() << ")"; 795 << " port: " << alternative_service.host_port_pair().port() << ")";
718 796
719 DCHECK(!request_info.url.SchemeIs(url::kFtpScheme)); 797 DCHECK(!request_info_.url.SchemeIs(url::kFtpScheme));
720 HostPortPair alternative_destination(alternative_service.host_port_pair()); 798 HostPortPair alternative_destination(alternative_service.host_port_pair());
721 ignore_result( 799 ignore_result(
722 ApplyHostMappingRules(request_info.url, &alternative_destination)); 800 ApplyHostMappingRules(request_info_.url, &alternative_destination));
723 801
724 alternative_job_.reset(job_factory_->CreateJob( 802 alternative_job_.reset(job_factory_->CreateAltSvcJob(
725 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, 803 this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_,
726 proxy_ssl_config, alternative_destination, origin_url, 804 server_ssl_config_, proxy_ssl_config_, alternative_destination,
727 alternative_service, enable_ip_based_pooling_, net_log_.net_log())); 805 origin_url, alternative_service, enable_ip_based_pooling_,
806 net_log_.net_log()));
728 807
729 main_job_is_blocked_ = true; 808 main_job_is_blocked_ = true;
730 alternative_job_->Start(request_->stream_type()); 809 alternative_job_->Start(request_->stream_type());
731 } else { 810 } else {
732 can_start_alternative_proxy_job_ = true; 811 ProxyServer alternative_proxy_server;
812 if (ShouldCreateAlternativeProxyServerJob(proxy_info_, request_info_.url,
813 &alternative_proxy_server)) {
814 DCHECK(!main_job_is_blocked_);
815 ProxyInfo alternative_proxy_info;
816 alternative_proxy_info.UseProxyServer(alternative_proxy_server);
817
818 alternative_job_.reset(job_factory_->CreateAltProxyJob(
819 this, ALTERNATIVE, session_, request_info_, priority_,
820 alternative_proxy_info, server_ssl_config_, proxy_ssl_config_,
821 destination, origin_url, alternative_proxy_server,
822 enable_ip_based_pooling_, net_log_.net_log()));
823
824 can_start_alternative_proxy_job_ = false;
825 main_job_is_blocked_ = true;
826 alternative_job_->Start(request_->stream_type());
827 }
733 } 828 }
734 // Even if |alternative_job| has already finished, it will not have notified 829 // 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 830 // the request yet, since we defer that to the next iteration of the
736 // MessageLoop, so starting |main_job_| is always safe. 831 // MessageLoop, so starting |main_job_| is always safe.
737 main_job_->Start(request_->stream_type()); 832 main_job_->Start(request_->stream_type());
833 return OK;
738 } 834 }
739 835
740 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { 836 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) {
741 DCHECK(request_); 837 DCHECK(request_);
742 DCHECK(job); 838 DCHECK(job);
743 DCHECK(job == alternative_job_.get() || job == main_job_.get()); 839 DCHECK(job == alternative_job_.get() || job == main_job_.get());
744 DCHECK(!job_bound_); 840 DCHECK(!job_bound_);
745 DCHECK(!bound_job_); 841 DCHECK(!bound_job_);
746 842
747 job_bound_ = true; 843 job_bound_ = true;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 } 919 }
824 920
825 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( 921 void HttpStreamFactoryImpl::JobController::MarkRequestComplete(
826 bool was_alpn_negotiated, 922 bool was_alpn_negotiated,
827 NextProto negotiated_protocol, 923 NextProto negotiated_protocol,
828 bool using_spdy) { 924 bool using_spdy) {
829 if (request_) 925 if (request_)
830 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy); 926 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy);
831 } 927 }
832 928
833 void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed( 929 void HttpStreamFactoryImpl::JobController::OnAlternativeServiceJobFailed(
834 int net_error) { 930 int net_error) {
835 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); 931 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE);
836 DCHECK_NE(OK, net_error); 932 DCHECK_NE(OK, net_error);
933 DCHECK_NE(kProtoUnknown, alternative_job_->alternative_service().protocol);
837 934
838 alternative_job_net_error_ = net_error; 935 alternative_job_net_error_ = net_error;
839 936 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 937
848 if (IsJobOrphaned(alternative_job_.get())) { 938 if (IsJobOrphaned(alternative_job_.get())) {
849 // If |request_| is gone then it must have been successfully served by 939 // If |request_| is gone then it must have been successfully served by
850 // |main_job_|. 940 // |main_job_|.
851 // If |request_| is bound to a different job, then it is being 941 // If |request_| is bound to a different job, then it is being
852 // successfully serverd by the main job. 942 // successfully serverd by the main job.
853 ReportBrokenAlternativeService(); 943 ReportBrokenAlternativeService();
854 } 944 }
855 } 945 }
856 946
947 void HttpStreamFactoryImpl::JobController::OnAlternativeProxyJobFailed(
948 int net_error) {
949 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE);
950 DCHECK_NE(OK, net_error);
951 DCHECK(alternative_job_->alternative_proxy_server().is_valid());
952
953 // Need to mark alt proxy as broken regardless whether the job is bound.
954 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
955 if (proxy_delegate) {
956 proxy_delegate->OnAlternativeProxyBroken(
957 alternative_job_->alternative_proxy_server());
958 }
959 }
960
857 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { 961 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() {
858 DCHECK(failed_alternative_service_.protocol != kProtoUnknown || 962 DCHECK(failed_alternative_service_.protocol != kProtoUnknown);
859 failed_alternative_proxy_server_.is_valid());
860 DCHECK_NE(OK, alternative_job_net_error_); 963 DCHECK_NE(OK, alternative_job_net_error_);
861 964
862 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", 965 int error_to_report = alternative_job_net_error_;
863 -alternative_job_net_error_); 966 alternative_job_net_error_ = OK;
967 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", -error_to_report);
864 968
865 if (alternative_job_net_error_ == ERR_NETWORK_CHANGED || 969 if (error_to_report == ERR_NETWORK_CHANGED ||
866 alternative_job_net_error_ == ERR_INTERNET_DISCONNECTED) { 970 error_to_report == ERR_INTERNET_DISCONNECTED) {
867 // No need to mark alternative service or proxy as broken. 971 // No need to mark alternative service or proxy as broken.
868 return; 972 return;
869 } 973 }
870 974
871 if (failed_alternative_proxy_server_.is_valid()) { 975 HistogramBrokenAlternateProtocolLocation(
872 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; 976 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
873 if (proxy_delegate) { 977 session_->http_server_properties()->MarkAlternativeServiceBroken(
874 proxy_delegate->OnAlternativeProxyBroken( 978 failed_alternative_service_);
875 failed_alternative_proxy_server_);
876 }
877 } else {
878 HistogramBrokenAlternateProtocolLocation(
879 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
880 session_->http_server_properties()->MarkAlternativeServiceBroken(
881 failed_alternative_service_);
882 }
883 } 979 }
884 980
885 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { 981 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() {
886 if (!request_ && !main_job_ && !alternative_job_) { 982 if (!request_ && !main_job_ && !alternative_job_) {
887 DCHECK(!bound_job_); 983 DCHECK(!bound_job_);
888 factory_->OnJobControllerComplete(this); 984 factory_->OnJobControllerComplete(this);
889 } 985 }
890 } 986 }
891 987
988 void HttpStreamFactoryImpl::JobController::NotifyRequestFailed(int rv) {
989 if (!request_)
990 return;
991 request_->OnStreamFailed(rv, server_ssl_config_);
992 }
993
892 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( 994 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules(
893 const GURL& url, 995 const GURL& url,
894 HostPortPair* endpoint) { 996 HostPortPair* endpoint) {
895 const HostMappingRules* mapping_rules = session_->params().host_mapping_rules; 997 const HostMappingRules* mapping_rules = session_->params().host_mapping_rules;
896 if (mapping_rules && mapping_rules->RewriteHost(endpoint)) { 998 if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
897 url::Replacements<char> replacements; 999 url::Replacements<char> replacements;
898 const std::string port_str = base::UintToString(endpoint->port()); 1000 const std::string port_str = base::UintToString(endpoint->port());
899 replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size())); 1001 replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
900 replacements.SetHost(endpoint->host().c_str(), 1002 replacements.SetHost(endpoint->host().c_str(),
901 url::Component(0, endpoint->host().size())); 1003 url::Component(0, endpoint->host().size()));
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 1127
1026 // Ask delegate to mark QUIC as broken for the origin. 1128 // Ask delegate to mark QUIC as broken for the origin.
1027 if (quic_advertised && quic_all_broken && delegate != nullptr) 1129 if (quic_advertised && quic_all_broken && delegate != nullptr)
1028 delegate->OnQuicBroken(); 1130 delegate->OnQuicBroken();
1029 1131
1030 return first_alternative_service; 1132 return first_alternative_service;
1031 } 1133 }
1032 1134
1033 bool HttpStreamFactoryImpl::JobController:: 1135 bool HttpStreamFactoryImpl::JobController::
1034 ShouldCreateAlternativeProxyServerJob( 1136 ShouldCreateAlternativeProxyServerJob(
1035 Job* job,
1036 const ProxyInfo& proxy_info, 1137 const ProxyInfo& proxy_info,
1037 const GURL& url, 1138 const GURL& url,
1038 ProxyServer* alternative_proxy_server) const { 1139 ProxyServer* alternative_proxy_server) const {
1039 DCHECK(!alternative_proxy_server->is_valid()); 1140 DCHECK(!alternative_proxy_server->is_valid());
1040 1141
1041 if (!enable_alternative_services_) 1142 if (!enable_alternative_services_)
1042 return false; 1143 return false;
1043 1144
1044 if (!can_start_alternative_proxy_job_) { 1145 if (!can_start_alternative_proxy_job_) {
1045 // Either an alternative service job or an alternative proxy server job has 1146 // Either an alternative service job or an alternative proxy server job has
1046 // already been started. 1147 // already been started.
1047 return false; 1148 return false;
1048 } 1149 }
1049 1150
1050 if (job->job_type() == ALTERNATIVE) {
1051 // If |job| is using alternative service, then alternative proxy server
1052 // should not be used.
1053 return false;
1054 }
1055
1056 if (is_preconnect_ || job->job_type() == PRECONNECT) {
1057 // Preconnects should be fetched using only the main job to keep the
1058 // resource utilization down.
1059 return false;
1060 }
1061
1062 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { 1151 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) {
1063 // Alternative proxy server job can be created only if |job| fetches the 1152 // Alternative proxy server job can be created only if |job| fetches the
1064 // |request_| through a non-QUIC proxy. 1153 // |request_| through a non-QUIC proxy.
1065 return false; 1154 return false;
1066 } 1155 }
1067 1156
1068 if (!url.SchemeIs(url::kHttpScheme)) { 1157 if (!url.SchemeIs(url::kHttpScheme)) {
1069 // Only HTTP URLs can be fetched through alternative proxy server, since the 1158 // Only HTTP URLs can be fetched through alternative proxy server, since the
1070 // alternative proxy server may not support fetching of URLs with other 1159 // alternative proxy server may not support fetching of URLs with other
1071 // schemes. 1160 // schemes.
1072 return false; 1161 return false;
1073 } 1162 }
1074 1163
1075 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; 1164 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
1076 if (!proxy_delegate) 1165 if (!proxy_delegate)
1077 return false; 1166 return false;
1078
1079 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), 1167 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(),
1080 alternative_proxy_server); 1168 alternative_proxy_server);
1081 1169
1082 if (!alternative_proxy_server->is_valid()) 1170 if (!alternative_proxy_server->is_valid())
1083 return false; 1171 return false;
1084 1172
1085 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server())); 1173 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server()));
1086 1174
1087 if (!alternative_proxy_server->is_https() && 1175 if (!alternative_proxy_server->is_https() &&
1088 !alternative_proxy_server->is_quic()) { 1176 !alternative_proxy_server->is_quic()) {
(...skipping 27 matching lines...) Expand all
1116 if (job->using_existing_quic_session()) { 1204 if (job->using_existing_quic_session()) {
1117 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, 1205 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE,
1118 proxy_server_used); 1206 proxy_server_used);
1119 return; 1207 return;
1120 } 1208 }
1121 1209
1122 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, 1210 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE,
1123 proxy_server_used); 1211 proxy_server_used);
1124 } 1212 }
1125 1213
1126 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() {
1127 if (!alternative_job_ || !request_)
1128 return;
1129 DCHECK(alternative_job_->alternative_proxy_server().is_valid());
1130 alternative_job_->Start(request_->stream_type());
1131 }
1132
1133 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { 1214 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const {
1134 return !request_ || (job_bound_ && bound_job_ != job); 1215 return !request_ || (job_bound_ && bound_job_ != job);
1135 } 1216 }
1136 1217
1218 int HttpStreamFactoryImpl::JobController::ReconsiderProxyAfterError(Job* job,
1219 int error) {
1220 // ReconsiderProxyAfterError() should only be called when the last job fails.
1221 DCHECK(!(alternative_job_ && main_job_));
1222 DCHECK(!pac_request_);
1223 DCHECK(session_);
1224
1225 if (!job->should_reconsider_proxy())
1226 return error;
1227
1228 DCHECK(!job->alternative_proxy_server().is_valid());
1229
1230 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG.
1231 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG)
1232 return error;
1233
1234 if (request_info_.load_flags & LOAD_BYPASS_PROXY)
1235 return error;
1236
1237 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
1238 session_->ssl_client_auth_cache()->Remove(
1239 proxy_info_.proxy_server().host_port_pair());
1240 }
1241
1242 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
1243 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
1244
1245 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1246 origin_url, request_info_.method, error, &proxy_info_, io_callback_,
1247 &pac_request_, session_->params().proxy_delegate, net_log_);
1248 if (rv == OK || rv == ERR_IO_PENDING) {
1249 RemoveRequestFromSpdySessionRequestMap();
1250 // Abandon all Jobs and start over.
1251 job_bound_ = false;
1252 bound_job_ = nullptr;
1253 alternative_job_.reset();
1254 main_job_.reset();
1255 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1256 } else {
1257 // If ReconsiderProxyAfterError() failed synchronously, it means
1258 // there was nothing left to fall-back to, so fail the transaction
1259 // with the last connection error we got.
1260 // TODO(eroman): This is a confusing contract, make it more obvious.
1261 rv = error;
1262 }
1263 return rv;
1264 }
1265
1137 } // namespace net 1266 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_stream_factory_impl_job_controller.h ('k') | net/http/http_stream_factory_impl_job_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698