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

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

Powered by Google App Engine
This is Rietveld 408576698