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

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: add one more test for ReconsiderProxyAfterError 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 // Returns parameters associated with the proxy resolution.
34 std::unique_ptr<base::Value> NetLogHttpStreamJobProxyServerResolved(
35 const ProxyServer& proxy_server,
36 NetLogCaptureMode /* capture_mode */) {
37 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
38
39 dict->SetString("proxy_server", proxy_server.is_valid()
40 ? proxy_server.ToPacString()
41 : std::string());
42 return std::move(dict);
43 }
44
45 } // namespace
46
32 // The maximum time to wait for the alternate job to complete before resuming 47 // The maximum time to wait for the alternate job to complete before resuming
33 // the main job. 48 // the main job.
34 const int kMaxDelayTimeForMainJobSecs = 3; 49 const int kMaxDelayTimeForMainJobSecs = 3;
35 50
36 std::unique_ptr<base::Value> NetLogJobControllerCallback( 51 std::unique_ptr<base::Value> NetLogJobControllerCallback(
37 const GURL* url, 52 const GURL* url,
38 bool is_preconnect, 53 bool is_preconnect,
39 NetLogCaptureMode /* capture_mode */) { 54 NetLogCaptureMode /* capture_mode */) {
40 auto dict = base::MakeUnique<base::DictionaryValue>(); 55 auto dict = base::MakeUnique<base::DictionaryValue>();
41 dict->SetString("url", url->possibly_invalid_spec()); 56 dict->SetString("url", url->possibly_invalid_spec());
42 dict->SetBoolean("is_preconnect", is_preconnect); 57 dict->SetBoolean("is_preconnect", is_preconnect);
43 return std::move(dict); 58 return std::move(dict);
44 } 59 }
45 60
46 HttpStreamFactoryImpl::JobController::JobController( 61 HttpStreamFactoryImpl::JobController::JobController(
47 HttpStreamFactoryImpl* factory, 62 HttpStreamFactoryImpl* factory,
48 HttpStreamRequest::Delegate* delegate, 63 HttpStreamRequest::Delegate* delegate,
49 HttpNetworkSession* session, 64 HttpNetworkSession* session,
50 JobFactory* job_factory, 65 JobFactory* job_factory,
51 const HttpRequestInfo& request_info, 66 const HttpRequestInfo& request_info,
52 bool is_preconnect, 67 bool is_preconnect,
53 bool enable_ip_based_pooling, 68 bool enable_ip_based_pooling,
54 bool enable_alternative_services) 69 bool enable_alternative_services,
70 const SSLConfig& server_ssl_config,
71 const SSLConfig& proxy_ssl_config)
55 : factory_(factory), 72 : factory_(factory),
56 session_(session), 73 session_(session),
57 job_factory_(job_factory), 74 job_factory_(job_factory),
58 request_(nullptr), 75 request_(nullptr),
59 delegate_(delegate), 76 delegate_(delegate),
60 is_preconnect_(is_preconnect), 77 is_preconnect_(is_preconnect),
61 enable_ip_based_pooling_(enable_ip_based_pooling), 78 enable_ip_based_pooling_(enable_ip_based_pooling),
62 enable_alternative_services_(enable_alternative_services), 79 enable_alternative_services_(enable_alternative_services),
63 alternative_job_net_error_(OK), 80 alternative_job_net_error_(OK),
64 job_bound_(false), 81 job_bound_(false),
65 main_job_is_blocked_(false), 82 main_job_is_blocked_(false),
66 main_job_is_resumed_(false), 83 main_job_is_resumed_(false),
67 bound_job_(nullptr), 84 bound_job_(nullptr),
68 can_start_alternative_proxy_job_(false), 85 can_start_alternative_proxy_job_(true),
69 privacy_mode_(PRIVACY_MODE_DISABLED), 86 privacy_mode_(PRIVACY_MODE_DISABLED),
87 next_state_(STATE_RESOLVE_PROXY),
88 pac_request_(nullptr),
70 net_log_( 89 net_log_(
71 NetLogWithSource::Make(session->net_log(), 90 NetLogWithSource::Make(session->net_log(),
72 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), 91 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)),
92 io_callback_(
93 base::Bind(&JobController::OnIOComplete, base::Unretained(this))),
94 request_info_(request_info),
95 server_ssl_config_(server_ssl_config),
96 proxy_ssl_config_(proxy_ssl_config),
97 num_streams_(0),
98 priority_(IDLE),
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 privacy_mode_ = request_info_.privacy_mode;
130 stream_type_ = stream_type;
131 priority_ = priority;
105 132
106 request_ = new Request(request_info.url, this, delegate, 133 request_ = new Request(request_info_.url, this, delegate,
107 websocket_handshake_stream_create_helper, 134 websocket_handshake_stream_create_helper,
108 source_net_log, stream_type); 135 source_net_log, stream_type);
109 // Associates |net_log_| with |source_net_log|. 136 // Associates |net_log_| with |source_net_log|.
110 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, 137 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND,
111 net_log_.source().ToEventParametersCallback()); 138 net_log_.source().ToEventParametersCallback());
112 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, 139 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND,
113 source_net_log.source().ToEventParametersCallback()); 140 source_net_log.source().ToEventParametersCallback());
114 141
115 CreateJobs(request_info, priority, server_ssl_config, proxy_ssl_config, 142 RunLoop(OK);
116 delegate, stream_type);
117
118 return request_; 143 return request_;
119 } 144 }
120 145
121 void HttpStreamFactoryImpl::JobController::Preconnect( 146 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_); 147 DCHECK(!main_job_);
127 DCHECK(!alternative_job_); 148 DCHECK(!alternative_job_);
128 DCHECK(is_preconnect_); 149 DCHECK(is_preconnect_);
129 150
130 privacy_mode_ = request_info.privacy_mode; 151 privacy_mode_ = request_info_.privacy_mode;
152 num_streams_ = num_streams;
131 153
132 HostPortPair destination(HostPortPair::FromURL(request_info.url)); 154 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
133 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); 155 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
134 156
135 const AlternativeService alternative_service = GetAlternativeServiceFor( 157 const AlternativeService alternative_service = GetAlternativeServiceFor(
136 request_info, nullptr, HttpStreamRequest::HTTP_STREAM); 158 request_info_, nullptr, HttpStreamRequest::HTTP_STREAM);
137 159
138 if (alternative_service.protocol != kProtoUnknown) { 160 if (alternative_service.protocol != kProtoUnknown) {
139 destination = alternative_service.host_port_pair(); 161 destination = alternative_service.host_port_pair();
140 ignore_result(ApplyHostMappingRules(request_info.url, &destination)); 162 ignore_result(ApplyHostMappingRules(request_info_.url, &destination));
141 } 163 }
142 164 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 } 165 }
153 166
154 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { 167 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const {
155 DCHECK(request_); 168 DCHECK(request_);
169 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE)
170 return session_->proxy_service()->GetLoadState(pac_request_);
156 DCHECK(main_job_ || alternative_job_); 171 DCHECK(main_job_ || alternative_job_);
157 if (bound_job_) 172 if (bound_job_)
158 return bound_job_->GetLoadState(); 173 return bound_job_->GetLoadState();
159 174
160 // Just pick the first one. 175 // Just pick the first one.
161 return main_job_ ? main_job_->GetLoadState() 176 return main_job_ ? main_job_->GetLoadState()
162 : alternative_job_->GetLoadState(); 177 : alternative_job_->GetLoadState();
163 } 178 }
164 179
165 void HttpStreamFactoryImpl::JobController::OnRequestComplete() { 180 void HttpStreamFactoryImpl::JobController::OnRequestComplete() {
(...skipping 14 matching lines...) Expand all
180 bound_job_ = nullptr; 195 bound_job_ = nullptr;
181 } 196 }
182 MaybeNotifyFactoryOfCompletion(); 197 MaybeNotifyFactoryOfCompletion();
183 } 198 }
184 199
185 int HttpStreamFactoryImpl::JobController::RestartTunnelWithProxyAuth() { 200 int HttpStreamFactoryImpl::JobController::RestartTunnelWithProxyAuth() {
186 DCHECK(bound_job_); 201 DCHECK(bound_job_);
187 return bound_job_->RestartTunnelWithProxyAuth(); 202 return bound_job_->RestartTunnelWithProxyAuth();
188 } 203 }
189 204
205 int HttpStreamFactoryImpl::JobController::ReconsiderProxyAfterError(Job* job,
206 int error) {
207 DCHECK(!pac_request_);
208 DCHECK(session_);
209
210 if (!job->reconsider_proxy())
211 return error;
212
213 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG.
214 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG)
215 return error;
216
217 if (request_info_.load_flags & LOAD_BYPASS_PROXY)
218 return error;
219
220 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
221 session_->ssl_client_auth_cache()->Remove(
222 proxy_info_.proxy_server().host_port_pair());
223 }
224
225 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
226 request_info_.url, request_info_.method, error, &proxy_info_,
227 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_);
228 if (rv == OK || rv == ERR_IO_PENDING) {
229 RemoveRequestFromSpdySessionRequestMap();
230 // Abandon all Jobs and start over.
231 job_bound_ = false;
232 bound_job_ = nullptr;
233 alternative_job_.reset();
234 main_job_.reset();
235 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
236 } else {
237 // If ReconsiderProxyAfterError() failed synchronously, it means
238 // there was nothing left to fall-back to, so fail the transaction
239 // with the last connection error we got.
240 // TODO(eroman): This is a confusing contract, make it more obvious.
241 rv = error;
242 }
243 return rv;
244 }
245
190 void HttpStreamFactoryImpl::JobController::SetPriority( 246 void HttpStreamFactoryImpl::JobController::SetPriority(
191 RequestPriority priority) { 247 RequestPriority priority) {
192 if (main_job_) { 248 if (main_job_) {
193 main_job_->SetPriority(priority); 249 main_job_->SetPriority(priority);
194 } 250 }
195 if (alternative_job_) { 251 if (alternative_job_) {
196 alternative_job_->SetPriority(priority); 252 alternative_job_->SetPriority(priority);
197 } 253 }
198 } 254 }
199 255
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 stream); 327 stream);
272 } 328 }
273 329
274 void HttpStreamFactoryImpl::JobController::OnStreamFailed( 330 void HttpStreamFactoryImpl::JobController::OnStreamFailed(
275 Job* job, 331 Job* job,
276 int status, 332 int status,
277 const SSLConfig& used_ssl_config) { 333 const SSLConfig& used_ssl_config) {
278 if (job->job_type() == ALTERNATIVE) { 334 if (job->job_type() == ALTERNATIVE) {
279 DCHECK_EQ(alternative_job_.get(), job); 335 DCHECK_EQ(alternative_job_.get(), job);
280 OnAlternativeJobFailed(status); 336 OnAlternativeJobFailed(status);
337 OnAlternativeProxyJobFailed(status);
281 } 338 }
282 339
283 MaybeResumeMainJob(job, base::TimeDelta()); 340 MaybeResumeMainJob(job, base::TimeDelta());
284 341
285 if (IsJobOrphaned(job)) { 342 if (IsJobOrphaned(job)) {
286 // We have bound a job to the associated Request, |job| has been orphaned. 343 // We have bound a job to the associated Request, |job| has been orphaned.
287 OnOrphanedJobComplete(job); 344 OnOrphanedJobComplete(job);
288 return; 345 return;
289 } 346 }
290 347
(...skipping 11 matching lines...) Expand all
302 } else { 359 } else {
303 DCHECK(job->job_type() == ALTERNATIVE); 360 DCHECK(job->job_type() == ALTERNATIVE);
304 alternative_job_.reset(); 361 alternative_job_.reset();
305 } 362 }
306 return; 363 return;
307 } else { 364 } else {
308 BindJob(job); 365 BindJob(job);
309 } 366 }
310 } 367 }
311 368
369 status = ReconsiderProxyAfterError(job, status);
370 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) {
371 RunLoop(OK);
372 return;
373 }
312 request_->OnStreamFailed(status, used_ssl_config); 374 request_->OnStreamFailed(status, used_ssl_config);
313 } 375 }
314 376
315 void HttpStreamFactoryImpl::JobController::OnCertificateError( 377 void HttpStreamFactoryImpl::JobController::OnCertificateError(
316 Job* job, 378 Job* job,
317 int status, 379 int status,
318 const SSLConfig& used_ssl_config, 380 const SSLConfig& used_ssl_config,
319 const SSLInfo& ssl_info) { 381 const SSLInfo& ssl_info) {
320 MaybeResumeMainJob(job, base::TimeDelta()); 382 MaybeResumeMainJob(job, base::TimeDelta());
321 383
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 BindJob(job); 457 BindJob(job);
396 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, 458 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info,
397 auth_controller); 459 auth_controller);
398 } 460 }
399 461
400 bool HttpStreamFactoryImpl::JobController::OnInitConnection( 462 bool HttpStreamFactoryImpl::JobController::OnInitConnection(
401 const ProxyInfo& proxy_info) { 463 const ProxyInfo& proxy_info) {
402 return factory_->OnInitConnection(*this, proxy_info, privacy_mode_); 464 return factory_->OnInitConnection(*this, proxy_info, privacy_mode_);
403 } 465 }
404 466
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( 467 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
445 Job* job, 468 Job* job,
446 const base::WeakPtr<SpdySession>& spdy_session, 469 const base::WeakPtr<SpdySession>& spdy_session,
447 bool direct) { 470 bool direct) {
448 DCHECK(job); 471 DCHECK(job);
449 DCHECK(job->using_spdy()); 472 DCHECK(job->using_spdy());
450 DCHECK(!is_preconnect_); 473 DCHECK(!is_preconnect_);
451 474
452 bool is_job_orphaned = IsJobOrphaned(job); 475 bool is_job_orphaned = IsJobOrphaned(job);
453 476
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 return base::trace_event::EstimateMemoryUsage(main_job_) + 705 return base::trace_event::EstimateMemoryUsage(main_job_) +
683 base::trace_event::EstimateMemoryUsage(alternative_job_); 706 base::trace_event::EstimateMemoryUsage(alternative_job_);
684 } 707 }
685 708
686 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: 709 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl::
687 JobController::websocket_handshake_stream_create_helper() { 710 JobController::websocket_handshake_stream_create_helper() {
688 DCHECK(request_); 711 DCHECK(request_);
689 return request_->websocket_handshake_stream_create_helper(); 712 return request_->websocket_handshake_stream_create_helper();
690 } 713 }
691 714
692 void HttpStreamFactoryImpl::JobController::CreateJobs( 715 void HttpStreamFactoryImpl::JobController::OnIOComplete(int result) {
693 const HttpRequestInfo& request_info, 716 RunLoop(result);
694 RequestPriority priority, 717 }
695 const SSLConfig& server_ssl_config, 718
696 const SSLConfig& proxy_ssl_config, 719 void HttpStreamFactoryImpl::JobController::RunLoop(int result) {
697 HttpStreamRequest::Delegate* delegate, 720 int rv = DoLoop(result);
698 HttpStreamRequest::StreamType stream_type) { 721 if (rv == ERR_IO_PENDING)
722 return;
723 if (rv != OK) {
724 DCHECK(!main_job_);
725 DCHECK(!alternative_job_);
726
727 if (!request_)
728 return;
729 request_->OnStreamFailed(rv, server_ssl_config_);
730 }
731 }
732
733 int HttpStreamFactoryImpl::JobController::DoLoop(int result) {
734 DCHECK_NE(next_state_, STATE_NONE);
735 int rv = result;
Bence 2017/05/03 14:11:10 I think it is okay to call the function argument r
xunjieli 2017/05/03 22:18:29 Done.
736 do {
737 State state = next_state_;
738 next_state_ = STATE_NONE;
739 switch (state) {
740 case STATE_RESOLVE_PROXY:
741 rv = DoResolveProxy();
742 break;
743 case STATE_RESOLVE_PROXY_COMPLETE:
744 rv = DoResolveProxyComplete(rv);
745 break;
746 case STATE_CREATE_JOBS:
747 rv = DoCreateJobs();
748 break;
749 default:
750 NOTREACHED() << "bad state";
751 break;
752 }
753 } while (next_state_ != STATE_NONE && rv != ERR_IO_PENDING);
754 return rv;
755 }
756
757 int HttpStreamFactoryImpl::JobController::DoResolveProxy() {
758 DCHECK(!pac_request_);
759 DCHECK(session_);
760
761 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
762
763 if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
764 proxy_info_.UseDirect();
765 return OK;
766 }
767
768 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
769 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
770
771 return session_->proxy_service()->ResolveProxy(
772 origin_url, request_info_.method, &proxy_info_, io_callback_,
773 &pac_request_, session_->params().proxy_delegate, net_log_);
774 }
775
776 int HttpStreamFactoryImpl::JobController::DoResolveProxyComplete(int rv) {
777 DCHECK_NE(ERR_IO_PENDING, rv);
778
779 pac_request_ = nullptr;
780 net_log_.AddEvent(
781 NetLogEventType::HTTP_STREAM_JOB_PROXY_SERVER_RESOLVED,
782 base::Bind(
783 &NetLogHttpStreamJobProxyServerResolved,
784 proxy_info_.is_empty() ? ProxyServer() : proxy_info_.proxy_server()));
785
786 if (rv == OK)
787 next_state_ = STATE_CREATE_JOBS;
788 return rv;
789 }
790
791 int HttpStreamFactoryImpl::JobController::DoCreateJobs() {
699 DCHECK(!main_job_); 792 DCHECK(!main_job_);
700 DCHECK(!alternative_job_); 793 DCHECK(!alternative_job_);
701 HostPortPair destination(HostPortPair::FromURL(request_info.url));
702 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
703 794
704 main_job_.reset(job_factory_->CreateJob( 795 HostPortPair destination(HostPortPair::FromURL(request_info_.url));
705 this, MAIN, session_, request_info, priority, server_ssl_config, 796 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 797
709 // Create an alternative job if alternative service is set up for this domain. 798 // Create an alternative job if alternative service is set up for this domain.
710 const AlternativeService alternative_service = 799 const AlternativeService alternative_service =
711 GetAlternativeServiceFor(request_info, delegate, stream_type); 800 GetAlternativeServiceFor(request_info_, delegate_, stream_type_);
712 801
713 if (alternative_service.protocol != kProtoUnknown) { 802 // Remove unsupported proxies from the list. ProxyServer::SCHEME_QUIC is not
714 // Never share connection with other jobs for FTP requests. 803 // yet supported.
715 DVLOG(1) << "Selected alternative service (host: " 804 int supported_proxies = ProxyServer::SCHEME_DIRECT |
716 << alternative_service.host_port_pair().host() 805 ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
717 << " port: " << alternative_service.host_port_pair().port() << ")"; 806 ProxyServer::SCHEME_SOCKS4 |
807 ProxyServer::SCHEME_SOCKS5;
718 808
719 DCHECK(!request_info.url.SchemeIs(url::kFtpScheme)); 809 if (session_->IsQuicEnabled())
720 HostPortPair alternative_destination(alternative_service.host_port_pair()); 810 supported_proxies |= ProxyServer::SCHEME_QUIC;
721 ignore_result( 811 proxy_info_.RemoveProxiesWithoutScheme(supported_proxies);
722 ApplyHostMappingRules(request_info.url, &alternative_destination));
723 812
724 alternative_job_.reset(job_factory_->CreateJob( 813 if (is_preconnect_) {
725 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, 814 // Due to how the socket pools handle priorities and idle sockets, only IDLE
726 proxy_ssl_config, alternative_destination, origin_url, 815 // priority currently makes sense for preconnects. The priority for
727 alternative_service, enable_ip_based_pooling_, net_log_.net_log())); 816 // preconnects is currently ignored (see RequestSocketsForPool()), but could
817 // be used at some point for proxy resolution or something.
818 main_job_.reset(job_factory_->CreateJob(
819 this, PRECONNECT, session_, request_info_, IDLE, proxy_info_,
820 server_ssl_config_, proxy_ssl_config_, destination, origin_url,
821 alternative_service, enable_ip_based_pooling_, session_->net_log()));
822 main_job_->Preconnect(num_streams_);
823 } else {
824 main_job_.reset(job_factory_->CreateJob(
825 this, MAIN, session_, request_info_, priority_, proxy_info_,
826 server_ssl_config_, proxy_ssl_config_, destination, origin_url,
827 enable_ip_based_pooling_, net_log_.net_log()));
828 if (alternative_service.protocol != kProtoUnknown) {
829 // Never share connection with other jobs for FTP requests.
830 DVLOG(1) << "Selected alternative service (host: "
831 << alternative_service.host_port_pair().host()
832 << " port: " << alternative_service.host_port_pair().port()
833 << ")";
728 834
729 main_job_is_blocked_ = true; 835 DCHECK(!request_info_.url.SchemeIs(url::kFtpScheme));
730 alternative_job_->Start(request_->stream_type()); 836 HostPortPair alternative_destination(
731 } else { 837 alternative_service.host_port_pair());
732 can_start_alternative_proxy_job_ = true; 838 ignore_result(
839 ApplyHostMappingRules(request_info_.url, &alternative_destination));
840
841 alternative_job_.reset(job_factory_->CreateJob(
842 this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_,
843 server_ssl_config_, proxy_ssl_config_, alternative_destination,
844 origin_url, alternative_service, enable_ip_based_pooling_,
845 net_log_.net_log()));
846
847 main_job_is_blocked_ = true;
848 alternative_job_->Start(request_->stream_type());
849 }
850 if (!alternative_job_) {
851 ProxyServer alternative_proxy_server;
852 if (ShouldCreateAlternativeProxyServerJob(proxy_info_, request_info_.url,
853 &alternative_proxy_server)) {
854 DCHECK(main_job_);
855 DCHECK(!main_job_is_blocked_);
856 ProxyInfo alternative_proxy_info;
857 alternative_proxy_info.UseProxyServer(alternative_proxy_server);
858
859 alternative_job_.reset(job_factory_->CreateJob(
860 this, ALTERNATIVE, session_, request_info_, priority_,
861 alternative_proxy_info, server_ssl_config_, proxy_ssl_config_,
862 destination, origin_url, alternative_proxy_server,
863 enable_ip_based_pooling_, net_log_.net_log()));
864
865 can_start_alternative_proxy_job_ = false;
866 main_job_is_blocked_ = true;
867
868 base::ThreadTaskRunnerHandle::Get()->PostTask(
869 FROM_HERE, base::Bind(&HttpStreamFactoryImpl::JobController::
870 StartAlternativeProxyServerJob,
871 ptr_factory_.GetWeakPtr()));
872 }
873 }
874 // Even if |alternative_job| has already finished, it will not have notified
875 // the request yet, since we defer that to the next iteration of the
876 // MessageLoop, so starting |main_job_| is always safe.
877 main_job_->Start(request_->stream_type());
733 } 878 }
734 // Even if |alternative_job| has already finished, it will not have notified 879 return OK;
735 // the request yet, since we defer that to the next iteration of the
736 // MessageLoop, so starting |main_job_| is always safe.
737 main_job_->Start(request_->stream_type());
738 } 880 }
739 881
740 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { 882 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) {
741 DCHECK(request_); 883 DCHECK(request_);
742 DCHECK(job); 884 DCHECK(job);
743 DCHECK(job == alternative_job_.get() || job == main_job_.get()); 885 DCHECK(job == alternative_job_.get() || job == main_job_.get());
744 DCHECK(!job_bound_); 886 DCHECK(!job_bound_);
745 DCHECK(!bound_job_); 887 DCHECK(!bound_job_);
746 888
747 job_bound_ = true; 889 job_bound_ = true;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 bool using_spdy) { 970 bool using_spdy) {
829 if (request_) 971 if (request_)
830 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy); 972 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy);
831 } 973 }
832 974
833 void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed( 975 void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed(
834 int net_error) { 976 int net_error) {
835 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); 977 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE);
836 DCHECK_NE(OK, net_error); 978 DCHECK_NE(OK, net_error);
837 979
980 DCHECK(alternative_job_->alternative_service().protocol != kProtoUnknown ||
981 alternative_job_->alternative_proxy_server().is_valid());
982 if (alternative_job_->alternative_proxy_server().is_valid())
983 return;
984
838 alternative_job_net_error_ = net_error; 985 alternative_job_net_error_ = net_error;
839 986
840 if (alternative_job_->alternative_proxy_server().is_valid()) { 987 failed_alternative_service_ = alternative_job_->alternative_service();
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 988
848 if (IsJobOrphaned(alternative_job_.get())) { 989 if (IsJobOrphaned(alternative_job_.get())) {
849 // If |request_| is gone then it must have been successfully served by 990 // If |request_| is gone then it must have been successfully served by
850 // |main_job_|. 991 // |main_job_|.
851 // If |request_| is bound to a different job, then it is being 992 // If |request_| is bound to a different job, then it is being
852 // successfully serverd by the main job. 993 // successfully serverd by the main job.
853 ReportBrokenAlternativeService(); 994 ReportBrokenAlternativeService();
854 } 995 }
855 } 996 }
856 997
998 void HttpStreamFactoryImpl::JobController::OnAlternativeProxyJobFailed(
999 int net_error) {
1000 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE);
1001 DCHECK_NE(OK, net_error);
1002
1003 if (!alternative_job_->alternative_proxy_server().is_valid())
1004 return;
1005 // Need to mark alt proxy as broken regardless whether the job is bound.
1006 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
1007 if (proxy_delegate) {
1008 proxy_delegate->OnAlternativeProxyBroken(
1009 alternative_job_->alternative_proxy_server());
1010 }
1011 }
1012
857 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { 1013 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() {
858 DCHECK(failed_alternative_service_.protocol != kProtoUnknown || 1014 DCHECK(failed_alternative_service_.protocol != kProtoUnknown);
859 failed_alternative_proxy_server_.is_valid());
860 DCHECK_NE(OK, alternative_job_net_error_); 1015 DCHECK_NE(OK, alternative_job_net_error_);
861 1016
862 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", 1017 int error_to_report = alternative_job_net_error_;
863 -alternative_job_net_error_); 1018 alternative_job_net_error_ = OK;
1019 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", -error_to_report);
864 1020
865 if (session_->params().quic_do_not_mark_as_broken_on_network_change && 1021 if (session_->params().quic_do_not_mark_as_broken_on_network_change &&
866 (alternative_job_net_error_ == ERR_NETWORK_CHANGED || 1022 (error_to_report == ERR_NETWORK_CHANGED ||
867 alternative_job_net_error_ == ERR_INTERNET_DISCONNECTED)) { 1023 error_to_report == ERR_INTERNET_DISCONNECTED)) {
868 // No need to mark alternative service or proxy as broken. 1024 // No need to mark alternative service or proxy as broken.
869 return; 1025 return;
870 } 1026 }
871 1027
872 if (failed_alternative_proxy_server_.is_valid()) { 1028 HistogramBrokenAlternateProtocolLocation(
873 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; 1029 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
874 if (proxy_delegate) { 1030 session_->http_server_properties()->MarkAlternativeServiceBroken(
875 proxy_delegate->OnAlternativeProxyBroken( 1031 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 } 1032 }
885 1033
886 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { 1034 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() {
887 if (!request_ && !main_job_ && !alternative_job_) { 1035 if (!request_ && !main_job_ && !alternative_job_) {
888 DCHECK(!bound_job_); 1036 DCHECK(!bound_job_);
889 factory_->OnJobControllerComplete(this); 1037 factory_->OnJobControllerComplete(this);
890 } 1038 }
891 } 1039 }
892 1040
893 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( 1041 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules(
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 1174
1027 // Ask delegate to mark QUIC as broken for the origin. 1175 // Ask delegate to mark QUIC as broken for the origin.
1028 if (quic_advertised && quic_all_broken && delegate != nullptr) 1176 if (quic_advertised && quic_all_broken && delegate != nullptr)
1029 delegate->OnQuicBroken(); 1177 delegate->OnQuicBroken();
1030 1178
1031 return first_alternative_service; 1179 return first_alternative_service;
1032 } 1180 }
1033 1181
1034 bool HttpStreamFactoryImpl::JobController:: 1182 bool HttpStreamFactoryImpl::JobController::
1035 ShouldCreateAlternativeProxyServerJob( 1183 ShouldCreateAlternativeProxyServerJob(
1036 Job* job,
1037 const ProxyInfo& proxy_info, 1184 const ProxyInfo& proxy_info,
1038 const GURL& url, 1185 const GURL& url,
1039 ProxyServer* alternative_proxy_server) const { 1186 ProxyServer* alternative_proxy_server) const {
1040 DCHECK(!alternative_proxy_server->is_valid()); 1187 DCHECK(!alternative_proxy_server->is_valid());
1041 1188
1042 if (!enable_alternative_services_) 1189 if (!enable_alternative_services_)
1043 return false; 1190 return false;
1044 1191
1045 if (!can_start_alternative_proxy_job_) { 1192 if (!can_start_alternative_proxy_job_) {
1046 // Either an alternative service job or an alternative proxy server job has 1193 // Either an alternative service job or an alternative proxy server job has
1047 // already been started. 1194 // already been started.
1048 return false; 1195 return false;
1049 } 1196 }
1050 1197
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()) { 1198 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 1199 // Alternative proxy server job can be created only if |job| fetches the
1065 // |request_| through a non-QUIC proxy. 1200 // |request_| through a non-QUIC proxy.
1066 return false; 1201 return false;
1067 } 1202 }
1068 1203
1069 if (!url.SchemeIs(url::kHttpScheme)) { 1204 if (!url.SchemeIs(url::kHttpScheme)) {
1070 // Only HTTP URLs can be fetched through alternative proxy server, since the 1205 // Only HTTP URLs can be fetched through alternative proxy server, since the
1071 // alternative proxy server may not support fetching of URLs with other 1206 // alternative proxy server may not support fetching of URLs with other
1072 // schemes. 1207 // schemes.
1073 return false; 1208 return false;
1074 } 1209 }
1075 1210
1076 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; 1211 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
1077 if (!proxy_delegate) 1212 if (!proxy_delegate)
1078 return false; 1213 return false;
1079
1080 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), 1214 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(),
1081 alternative_proxy_server); 1215 alternative_proxy_server);
1082 1216
1083 if (!alternative_proxy_server->is_valid()) 1217 if (!alternative_proxy_server->is_valid())
1084 return false; 1218 return false;
1085 1219
1086 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server())); 1220 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server()));
1087 1221
1088 if (!alternative_proxy_server->is_https() && 1222 if (!alternative_proxy_server->is_https() &&
1089 !alternative_proxy_server->is_quic()) { 1223 !alternative_proxy_server->is_quic()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 return; 1263 return;
1130 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); 1264 DCHECK(alternative_job_->alternative_proxy_server().is_valid());
1131 alternative_job_->Start(request_->stream_type()); 1265 alternative_job_->Start(request_->stream_type());
1132 } 1266 }
1133 1267
1134 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { 1268 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const {
1135 return !request_ || (job_bound_ && bound_job_ != job); 1269 return !request_ || (job_bound_ && bound_job_ != job);
1136 } 1270 }
1137 1271
1138 } // namespace net 1272 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698