OLD | NEW |
---|---|
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_stream_factory_impl_job_controller.h" | 5 #include "net/http/http_stream_factory_impl_job_controller.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 #include "net/log/net_log_capture_mode.h" | 21 #include "net/log/net_log_capture_mode.h" |
22 #include "net/log/net_log_event_type.h" | 22 #include "net/log/net_log_event_type.h" |
23 #include "net/log/net_log_source.h" | 23 #include "net/log/net_log_source.h" |
24 #include "net/log/net_log_with_source.h" | 24 #include "net/log/net_log_with_source.h" |
25 #include "net/proxy/proxy_server.h" | 25 #include "net/proxy/proxy_server.h" |
26 #include "net/spdy/chromium/spdy_session.h" | 26 #include "net/spdy/chromium/spdy_session.h" |
27 #include "url/url_constants.h" | 27 #include "url/url_constants.h" |
28 | 28 |
29 namespace net { | 29 namespace net { |
30 | 30 |
31 namespace { | |
32 | |
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 | |
47 // The maximum time to wait for the alternate job to complete before resuming | 31 // The maximum time to wait for the alternate job to complete before resuming |
48 // the main job. | 32 // the main job. |
49 const int kMaxDelayTimeForMainJobSecs = 3; | 33 const int kMaxDelayTimeForMainJobSecs = 3; |
50 | 34 |
51 std::unique_ptr<base::Value> NetLogJobControllerCallback( | 35 std::unique_ptr<base::Value> NetLogJobControllerCallback( |
52 const GURL* url, | 36 const GURL* url, |
53 bool is_preconnect, | 37 bool is_preconnect, |
54 NetLogCaptureMode /* capture_mode */) { | 38 NetLogCaptureMode /* capture_mode */) { |
55 auto dict = base::MakeUnique<base::DictionaryValue>(); | 39 auto dict = base::MakeUnique<base::DictionaryValue>(); |
56 dict->SetString("url", url->possibly_invalid_spec()); | 40 dict->SetString("url", url->possibly_invalid_spec()); |
57 dict->SetBoolean("is_preconnect", is_preconnect); | 41 dict->SetBoolean("is_preconnect", is_preconnect); |
58 return std::move(dict); | 42 return std::move(dict); |
59 } | 43 } |
60 | 44 |
61 HttpStreamFactoryImpl::JobController::JobController( | 45 HttpStreamFactoryImpl::JobController::JobController( |
62 HttpStreamFactoryImpl* factory, | 46 HttpStreamFactoryImpl* factory, |
63 HttpStreamRequest::Delegate* delegate, | 47 HttpStreamRequest::Delegate* delegate, |
64 HttpNetworkSession* session, | 48 HttpNetworkSession* session, |
65 JobFactory* job_factory, | 49 JobFactory* job_factory, |
66 const HttpRequestInfo& request_info, | 50 const HttpRequestInfo& request_info, |
67 bool is_preconnect, | 51 bool is_preconnect, |
68 bool enable_ip_based_pooling, | 52 bool enable_ip_based_pooling, |
69 bool enable_alternative_services, | 53 bool enable_alternative_services) |
70 const SSLConfig& server_ssl_config, | |
71 const SSLConfig& proxy_ssl_config) | |
72 : factory_(factory), | 54 : factory_(factory), |
73 session_(session), | 55 session_(session), |
74 job_factory_(job_factory), | 56 job_factory_(job_factory), |
75 request_(nullptr), | 57 request_(nullptr), |
76 delegate_(delegate), | 58 delegate_(delegate), |
77 is_preconnect_(is_preconnect), | 59 is_preconnect_(is_preconnect), |
78 enable_ip_based_pooling_(enable_ip_based_pooling), | 60 enable_ip_based_pooling_(enable_ip_based_pooling), |
79 enable_alternative_services_(enable_alternative_services), | 61 enable_alternative_services_(enable_alternative_services), |
80 alternative_job_net_error_(OK), | 62 alternative_job_net_error_(OK), |
81 job_bound_(false), | 63 job_bound_(false), |
82 main_job_is_blocked_(false), | 64 main_job_is_blocked_(false), |
83 main_job_is_resumed_(false), | 65 main_job_is_resumed_(false), |
84 bound_job_(nullptr), | 66 bound_job_(nullptr), |
85 can_start_alternative_proxy_job_(true), | 67 can_start_alternative_proxy_job_(false), |
86 next_state_(STATE_RESOLVE_PROXY), | 68 privacy_mode_(PRIVACY_MODE_DISABLED), |
87 pac_request_(nullptr), | |
88 io_callback_( | |
89 base::Bind(&JobController::OnIOComplete, base::Unretained(this))), | |
90 request_info_(request_info), | |
91 server_ssl_config_(server_ssl_config), | |
92 proxy_ssl_config_(proxy_ssl_config), | |
93 num_streams_(0), | |
94 priority_(IDLE), | |
95 net_log_( | 69 net_log_( |
96 NetLogWithSource::Make(session->net_log(), | 70 NetLogWithSource::Make(session->net_log(), |
97 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), | 71 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), |
98 ptr_factory_(this) { | 72 ptr_factory_(this) { |
99 DCHECK(factory); | 73 DCHECK(factory); |
100 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, | 74 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, |
101 base::Bind(&NetLogJobControllerCallback, | 75 base::Bind(&NetLogJobControllerCallback, |
102 &request_info.url, is_preconnect)); | 76 &request_info.url, is_preconnect)); |
103 } | 77 } |
104 | 78 |
105 HttpStreamFactoryImpl::JobController::~JobController() { | 79 HttpStreamFactoryImpl::JobController::~JobController() { |
106 main_job_.reset(); | 80 main_job_.reset(); |
107 alternative_job_.reset(); | 81 alternative_job_.reset(); |
108 bound_job_ = nullptr; | 82 bound_job_ = nullptr; |
109 if (pac_request_) { | |
110 // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is | |
111 // resolved. | |
112 CHECK_EQ(STATE_RESOLVE_PROXY_COMPLETE, next_state_); | |
113 session_->proxy_service()->CancelPacRequest(pac_request_); | |
114 } | |
115 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); | 83 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); |
116 } | 84 } |
117 | 85 |
118 bool HttpStreamFactoryImpl::JobController::for_websockets() { | 86 bool HttpStreamFactoryImpl::JobController::for_websockets() { |
119 return factory_->for_websockets_; | 87 return factory_->for_websockets_; |
120 } | 88 } |
121 | 89 |
122 std::unique_ptr<HttpStreamFactoryImpl::Request> | 90 HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start( |
123 HttpStreamFactoryImpl::JobController::Start( | 91 const HttpRequestInfo& request_info, |
124 HttpStreamRequest::Delegate* delegate, | 92 HttpStreamRequest::Delegate* delegate, |
125 WebSocketHandshakeStreamBase::CreateHelper* | 93 WebSocketHandshakeStreamBase::CreateHelper* |
126 websocket_handshake_stream_create_helper, | 94 websocket_handshake_stream_create_helper, |
127 const NetLogWithSource& source_net_log, | 95 const NetLogWithSource& source_net_log, |
128 HttpStreamRequest::StreamType stream_type, | 96 HttpStreamRequest::StreamType stream_type, |
129 RequestPriority priority) { | 97 RequestPriority priority, |
98 const SSLConfig& server_ssl_config, | |
99 const SSLConfig& proxy_ssl_config) { | |
130 DCHECK(factory_); | 100 DCHECK(factory_); |
131 DCHECK(!request_); | 101 DCHECK(!request_); |
132 | 102 |
133 stream_type_ = stream_type; | 103 privacy_mode_ = request_info.privacy_mode; |
134 priority_ = priority; | |
135 | 104 |
136 auto request = base::MakeUnique<Request>( | 105 request_ = new Request(request_info.url, this, delegate, |
137 request_info_.url, this, delegate, | 106 websocket_handshake_stream_create_helper, |
138 websocket_handshake_stream_create_helper, source_net_log, stream_type); | 107 source_net_log, stream_type); |
139 // Keep a raw pointer but release ownership of Request instance. | |
140 request_ = request.get(); | |
141 | |
142 // Associates |net_log_| with |source_net_log|. | 108 // Associates |net_log_| with |source_net_log|. |
143 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, | 109 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, |
144 net_log_.source().ToEventParametersCallback()); | 110 net_log_.source().ToEventParametersCallback()); |
145 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, | 111 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, |
146 source_net_log.source().ToEventParametersCallback()); | 112 source_net_log.source().ToEventParametersCallback()); |
147 | 113 |
148 RunLoop(OK); | 114 CreateJobs(request_info, priority, server_ssl_config, proxy_ssl_config, |
149 return request; | 115 delegate, stream_type); |
116 | |
117 return request_; | |
150 } | 118 } |
151 | 119 |
152 void HttpStreamFactoryImpl::JobController::Preconnect(int num_streams) { | 120 void HttpStreamFactoryImpl::JobController::Preconnect( |
121 int num_streams, | |
122 const HttpRequestInfo& request_info, | |
123 const SSLConfig& server_ssl_config, | |
124 const SSLConfig& proxy_ssl_config) { | |
153 DCHECK(!main_job_); | 125 DCHECK(!main_job_); |
154 DCHECK(!alternative_job_); | 126 DCHECK(!alternative_job_); |
155 DCHECK(is_preconnect_); | 127 DCHECK(is_preconnect_); |
156 | 128 |
157 stream_type_ = HttpStreamRequest::HTTP_STREAM; | 129 privacy_mode_ = request_info.privacy_mode; |
158 num_streams_ = num_streams; | |
159 | 130 |
160 RunLoop(OK); | 131 HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
132 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | |
133 | |
134 const AlternativeService alternative_service = | |
135 GetAlternativeServiceInfoFor(request_info, nullptr, | |
136 HttpStreamRequest::HTTP_STREAM) | |
137 .alternative_service; | |
138 | |
139 if (alternative_service.protocol != kProtoUnknown) { | |
140 destination = alternative_service.host_port_pair(); | |
141 ignore_result(ApplyHostMappingRules(request_info.url, &destination)); | |
142 } | |
143 | |
144 // Due to how the socket pools handle priorities and idle sockets, only IDLE | |
145 // priority currently makes sense for preconnects. The priority for | |
146 // preconnects is currently ignored (see RequestSocketsForPool()), but could | |
147 // be used at some point for proxy resolution or something. | |
148 main_job_.reset(job_factory_->CreateJob( | |
149 this, PRECONNECT, session_, request_info, IDLE, server_ssl_config, | |
150 proxy_ssl_config, destination, origin_url, alternative_service, | |
151 enable_ip_based_pooling_, session_->net_log())); | |
152 main_job_->Preconnect(num_streams); | |
161 } | 153 } |
162 | 154 |
163 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { | 155 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { |
164 DCHECK(request_); | 156 DCHECK(request_); |
165 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) | 157 DCHECK(main_job_ || alternative_job_); |
166 return session_->proxy_service()->GetLoadState(pac_request_); | |
167 if (bound_job_) | 158 if (bound_job_) |
168 return bound_job_->GetLoadState(); | 159 return bound_job_->GetLoadState(); |
169 if (main_job_) | 160 |
170 return main_job_->GetLoadState(); | 161 // Just pick the first one. |
171 if (alternative_job_) | 162 return main_job_ ? main_job_->GetLoadState() |
172 return alternative_job_->GetLoadState(); | 163 : alternative_job_->GetLoadState(); |
173 // When proxy resolution fails, there is no job created and | |
174 // NotifyRequestFailed() is executed one message loop iteration later. | |
175 return LOAD_STATE_IDLE; | |
176 } | 164 } |
177 | 165 |
178 void HttpStreamFactoryImpl::JobController::OnRequestComplete() { | 166 void HttpStreamFactoryImpl::JobController::OnRequestComplete() { |
179 CancelJobs(); | 167 CancelJobs(); |
180 DCHECK(request_); | 168 DCHECK(request_); |
181 request_ = nullptr; | 169 request_ = nullptr; |
182 if (bound_job_) { | 170 if (bound_job_) { |
183 if (bound_job_->job_type() == MAIN) { | 171 if (bound_job_->job_type() == MAIN) { |
184 main_job_.reset(); | 172 main_job_.reset(); |
185 // |alternative_job_| can be non-null if |main_job_| is resumed after | 173 // |alternative_job_| can be non-null if |main_job_| is resumed after |
(...skipping 22 matching lines...) Expand all Loading... | |
208 if (alternative_job_) { | 196 if (alternative_job_) { |
209 alternative_job_->SetPriority(priority); | 197 alternative_job_->SetPriority(priority); |
210 } | 198 } |
211 } | 199 } |
212 | 200 |
213 void HttpStreamFactoryImpl::JobController::OnStreamReady( | 201 void HttpStreamFactoryImpl::JobController::OnStreamReady( |
214 Job* job, | 202 Job* job, |
215 const SSLConfig& used_ssl_config) { | 203 const SSLConfig& used_ssl_config) { |
216 DCHECK(job); | 204 DCHECK(job); |
217 | 205 |
218 factory_->OnStreamReady(job->proxy_info(), request_info_.privacy_mode); | 206 factory_->OnStreamReady(job->proxy_info(), privacy_mode_); |
219 | 207 |
220 if (IsJobOrphaned(job)) { | 208 if (IsJobOrphaned(job)) { |
221 // We have bound a job to the associated Request, |job| has been orphaned. | 209 // We have bound a job to the associated Request, |job| has been orphaned. |
222 OnOrphanedJobComplete(job); | 210 OnOrphanedJobComplete(job); |
223 return; | 211 return; |
224 } | 212 } |
225 std::unique_ptr<HttpStream> stream = job->ReleaseStream(); | 213 std::unique_ptr<HttpStream> stream = job->ReleaseStream(); |
226 DCHECK(stream); | 214 DCHECK(stream); |
227 | 215 |
228 MarkRequestComplete(job->was_alpn_negotiated(), job->negotiated_protocol(), | 216 MarkRequestComplete(job->was_alpn_negotiated(), job->negotiated_protocol(), |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, | 271 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, |
284 stream); | 272 stream); |
285 } | 273 } |
286 | 274 |
287 void HttpStreamFactoryImpl::JobController::OnStreamFailed( | 275 void HttpStreamFactoryImpl::JobController::OnStreamFailed( |
288 Job* job, | 276 Job* job, |
289 int status, | 277 int status, |
290 const SSLConfig& used_ssl_config) { | 278 const SSLConfig& used_ssl_config) { |
291 if (job->job_type() == ALTERNATIVE) { | 279 if (job->job_type() == ALTERNATIVE) { |
292 DCHECK_EQ(alternative_job_.get(), job); | 280 DCHECK_EQ(alternative_job_.get(), job); |
293 if (alternative_job_->alternative_proxy_server().is_valid()) { | 281 OnAlternativeJobFailed(status); |
294 OnAlternativeProxyJobFailed(status); | |
295 } else { | |
296 OnAlternativeServiceJobFailed(status); | |
297 } | |
298 } | 282 } |
299 | 283 |
300 MaybeResumeMainJob(job, base::TimeDelta()); | 284 MaybeResumeMainJob(job, base::TimeDelta()); |
301 | 285 |
302 if (IsJobOrphaned(job)) { | 286 if (IsJobOrphaned(job)) { |
303 // We have bound a job to the associated Request, |job| has been orphaned. | 287 // We have bound a job to the associated Request, |job| has been orphaned. |
304 OnOrphanedJobComplete(job); | 288 OnOrphanedJobComplete(job); |
305 return; | 289 return; |
306 } | 290 } |
307 | 291 |
(...skipping 11 matching lines...) Expand all Loading... | |
319 } else { | 303 } else { |
320 DCHECK(job->job_type() == ALTERNATIVE); | 304 DCHECK(job->job_type() == ALTERNATIVE); |
321 alternative_job_.reset(); | 305 alternative_job_.reset(); |
322 } | 306 } |
323 return; | 307 return; |
324 } else { | 308 } else { |
325 BindJob(job); | 309 BindJob(job); |
326 } | 310 } |
327 } | 311 } |
328 | 312 |
329 status = ReconsiderProxyAfterError(job, status); | |
330 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) { | |
331 RunLoop(OK); | |
332 return; | |
333 } | |
334 request_->OnStreamFailed(status, used_ssl_config); | 313 request_->OnStreamFailed(status, used_ssl_config); |
335 } | 314 } |
336 | 315 |
337 void HttpStreamFactoryImpl::JobController::OnCertificateError( | 316 void HttpStreamFactoryImpl::JobController::OnCertificateError( |
338 Job* job, | 317 Job* job, |
339 int status, | 318 int status, |
340 const SSLConfig& used_ssl_config, | 319 const SSLConfig& used_ssl_config, |
341 const SSLInfo& ssl_info) { | 320 const SSLInfo& ssl_info) { |
342 MaybeResumeMainJob(job, base::TimeDelta()); | 321 MaybeResumeMainJob(job, base::TimeDelta()); |
343 | 322 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
414 if (!request_) | 393 if (!request_) |
415 return; | 394 return; |
416 if (!bound_job_) | 395 if (!bound_job_) |
417 BindJob(job); | 396 BindJob(job); |
418 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, | 397 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, |
419 auth_controller); | 398 auth_controller); |
420 } | 399 } |
421 | 400 |
422 bool HttpStreamFactoryImpl::JobController::OnInitConnection( | 401 bool HttpStreamFactoryImpl::JobController::OnInitConnection( |
423 const ProxyInfo& proxy_info) { | 402 const ProxyInfo& proxy_info) { |
424 return factory_->OnInitConnection(*this, proxy_info, | 403 return factory_->OnInitConnection(*this, proxy_info, privacy_mode_); |
425 request_info_.privacy_mode); | 404 } |
405 | |
406 void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete( | |
407 Job* job, | |
408 const HttpRequestInfo& request_info, | |
409 RequestPriority priority, | |
410 const SSLConfig& server_ssl_config, | |
411 const SSLConfig& proxy_ssl_config, | |
412 HttpStreamRequest::StreamType stream_type) { | |
413 DCHECK(job); | |
414 | |
415 ProxyServer alternative_proxy_server; | |
416 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), | |
417 request_info.url, | |
418 &alternative_proxy_server)) { | |
419 return; | |
420 } | |
421 | |
422 DCHECK(main_job_); | |
423 DCHECK_EQ(MAIN, job->job_type()); | |
424 DCHECK(!alternative_job_); | |
425 DCHECK(!main_job_is_blocked_); | |
426 | |
427 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | |
428 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | |
429 | |
430 alternative_job_.reset(job_factory_->CreateJob( | |
431 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, | |
432 proxy_ssl_config, destination, origin_url, alternative_proxy_server, | |
433 enable_ip_based_pooling_, job->net_log().net_log())); | |
434 | |
435 can_start_alternative_proxy_job_ = false; | |
436 main_job_is_blocked_ = true; | |
437 | |
438 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
439 FROM_HERE, | |
440 base::Bind( | |
441 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, | |
442 ptr_factory_.GetWeakPtr())); | |
426 } | 443 } |
427 | 444 |
428 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( | 445 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( |
429 Job* job, | 446 Job* job, |
430 const base::WeakPtr<SpdySession>& spdy_session, | 447 const base::WeakPtr<SpdySession>& spdy_session, |
431 bool direct) { | 448 bool direct) { |
432 DCHECK(job); | 449 DCHECK(job); |
433 DCHECK(job->using_spdy()); | 450 DCHECK(job->using_spdy()); |
434 DCHECK(!is_preconnect_); | 451 DCHECK(!is_preconnect_); |
435 | 452 |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
666 return base::trace_event::EstimateMemoryUsage(main_job_) + | 683 return base::trace_event::EstimateMemoryUsage(main_job_) + |
667 base::trace_event::EstimateMemoryUsage(alternative_job_); | 684 base::trace_event::EstimateMemoryUsage(alternative_job_); |
668 } | 685 } |
669 | 686 |
670 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: | 687 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: |
671 JobController::websocket_handshake_stream_create_helper() { | 688 JobController::websocket_handshake_stream_create_helper() { |
672 DCHECK(request_); | 689 DCHECK(request_); |
673 return request_->websocket_handshake_stream_create_helper(); | 690 return request_->websocket_handshake_stream_create_helper(); |
674 } | 691 } |
675 | 692 |
676 void HttpStreamFactoryImpl::JobController::OnIOComplete(int result) { | 693 void HttpStreamFactoryImpl::JobController::CreateJobs( |
677 RunLoop(result); | 694 const HttpRequestInfo& request_info, |
678 } | 695 RequestPriority priority, |
679 | 696 const SSLConfig& server_ssl_config, |
680 void HttpStreamFactoryImpl::JobController::RunLoop(int result) { | 697 const SSLConfig& proxy_ssl_config, |
681 int rv = DoLoop(result); | 698 HttpStreamRequest::Delegate* delegate, |
682 if (rv == ERR_IO_PENDING) | 699 HttpStreamRequest::StreamType stream_type) { |
683 return; | |
684 if (rv != OK) { | |
685 // DoLoop can only fail during proxy resolution step which happens before | |
686 // any jobs are created. Notify |request_| of the failure one message loop | |
687 // iteration later to avoid re-entrancy. | |
688 DCHECK(!main_job_); | |
689 DCHECK(!alternative_job_); | |
690 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
691 FROM_HERE, | |
692 base::Bind(&HttpStreamFactoryImpl::JobController::NotifyRequestFailed, | |
693 ptr_factory_.GetWeakPtr(), rv)); | |
694 } | |
695 } | |
696 | |
697 int HttpStreamFactoryImpl::JobController::DoLoop(int rv) { | |
698 DCHECK_NE(next_state_, STATE_NONE); | |
699 do { | |
700 State state = next_state_; | |
701 next_state_ = STATE_NONE; | |
702 switch (state) { | |
703 case STATE_RESOLVE_PROXY: | |
704 DCHECK_EQ(OK, rv); | |
705 rv = DoResolveProxy(); | |
706 break; | |
707 case STATE_RESOLVE_PROXY_COMPLETE: | |
708 rv = DoResolveProxyComplete(rv); | |
709 break; | |
710 case STATE_CREATE_JOBS: | |
711 DCHECK_EQ(OK, rv); | |
712 rv = DoCreateJobs(); | |
713 break; | |
714 default: | |
715 NOTREACHED() << "bad state"; | |
716 break; | |
717 } | |
718 } while (next_state_ != STATE_NONE && rv != ERR_IO_PENDING); | |
719 return rv; | |
720 } | |
721 | |
722 int HttpStreamFactoryImpl::JobController::DoResolveProxy() { | |
723 // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is | |
724 // resolved. | |
725 CHECK(!pac_request_); | |
726 DCHECK(session_); | |
727 | |
728 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | |
729 | |
730 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { | |
731 proxy_info_.UseDirect(); | |
732 return OK; | |
733 } | |
734 | |
735 HostPortPair destination(HostPortPair::FromURL(request_info_.url)); | |
736 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); | |
737 | |
738 return session_->proxy_service()->ResolveProxy( | |
739 origin_url, request_info_.method, &proxy_info_, io_callback_, | |
740 &pac_request_, session_->params().proxy_delegate, net_log_); | |
741 } | |
742 | |
743 int HttpStreamFactoryImpl::JobController::DoResolveProxyComplete(int rv) { | |
744 DCHECK_NE(ERR_IO_PENDING, rv); | |
745 | |
746 pac_request_ = nullptr; | |
747 net_log_.AddEvent( | |
748 NetLogEventType::HTTP_STREAM_JOB_PROXY_SERVER_RESOLVED, | |
749 base::Bind( | |
750 &NetLogHttpStreamJobProxyServerResolved, | |
751 proxy_info_.is_empty() ? ProxyServer() : proxy_info_.proxy_server())); | |
752 | |
753 if (rv != OK) | |
754 return rv; | |
755 // Remove unsupported proxies from the list. | |
756 int supported_proxies = ProxyServer::SCHEME_DIRECT | | |
757 ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS | | |
758 ProxyServer::SCHEME_SOCKS4 | | |
759 ProxyServer::SCHEME_SOCKS5; | |
760 if (session_->IsQuicEnabled()) | |
761 supported_proxies |= ProxyServer::SCHEME_QUIC; | |
762 proxy_info_.RemoveProxiesWithoutScheme(supported_proxies); | |
763 | |
764 if (proxy_info_.is_empty()) { | |
765 // No proxies/direct to choose from. | |
766 return ERR_NO_SUPPORTED_PROXIES; | |
767 } | |
768 | |
769 next_state_ = STATE_CREATE_JOBS; | |
770 return rv; | |
771 } | |
772 | |
773 int HttpStreamFactoryImpl::JobController::DoCreateJobs() { | |
774 DCHECK(!main_job_); | 700 DCHECK(!main_job_); |
775 DCHECK(!alternative_job_); | 701 DCHECK(!alternative_job_); |
702 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | |
703 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | |
776 | 704 |
777 HostPortPair destination(HostPortPair::FromURL(request_info_.url)); | 705 main_job_.reset(job_factory_->CreateJob( |
778 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); | 706 this, MAIN, session_, request_info, priority, server_ssl_config, |
707 proxy_ssl_config, destination, origin_url, enable_ip_based_pooling_, | |
708 net_log_.net_log())); | |
779 | 709 |
780 // Create an alternative job if alternative service is set up for this domain. | 710 // Create an alternative job if alternative service is set up for this domain. |
781 const AlternativeService alternative_service = | 711 const AlternativeService alternative_service = |
782 GetAlternativeServiceInfoFor(request_info_, delegate_, stream_type_) | 712 GetAlternativeServiceInfoFor(request_info, delegate, stream_type) |
783 .alternative_service; | 713 .alternative_service; |
784 | 714 |
785 if (is_preconnect_) { | |
786 // Due to how the socket pools handle priorities and idle sockets, only IDLE | |
787 // priority currently makes sense for preconnects. The priority for | |
788 // preconnects is currently ignored (see RequestSocketsForPool()), but could | |
789 // be used at some point for proxy resolution or something. | |
790 main_job_ = job_factory_->CreateAltSvcJob( | |
Zhongyi Shi
2017/05/22 19:05:39
FYI, Ryan and I were just looking at the code toda
xunjieli
2017/05/22 19:15:00
Acknowledged. Good catch! Will do this when reland
| |
791 this, PRECONNECT, session_, request_info_, IDLE, proxy_info_, | |
792 server_ssl_config_, proxy_ssl_config_, destination, origin_url, | |
793 alternative_service, enable_ip_based_pooling_, session_->net_log()); | |
794 main_job_->Preconnect(num_streams_); | |
795 return OK; | |
796 } | |
797 main_job_ = job_factory_->CreateMainJob( | |
798 this, MAIN, session_, request_info_, priority_, proxy_info_, | |
799 server_ssl_config_, proxy_ssl_config_, destination, origin_url, | |
800 enable_ip_based_pooling_, net_log_.net_log()); | |
801 // Alternative Service can only be set for HTTPS requests while Alternative | |
802 // Proxy is set for HTTP requests. | |
803 if (alternative_service.protocol != kProtoUnknown) { | 715 if (alternative_service.protocol != kProtoUnknown) { |
804 // Never share connection with other jobs for FTP requests. | 716 // Never share connection with other jobs for FTP requests. |
805 DVLOG(1) << "Selected alternative service (host: " | 717 DVLOG(1) << "Selected alternative service (host: " |
806 << alternative_service.host_port_pair().host() | 718 << alternative_service.host_port_pair().host() |
807 << " port: " << alternative_service.host_port_pair().port() << ")"; | 719 << " port: " << alternative_service.host_port_pair().port() << ")"; |
808 | 720 |
809 DCHECK(!request_info_.url.SchemeIs(url::kFtpScheme)); | 721 DCHECK(!request_info.url.SchemeIs(url::kFtpScheme)); |
810 HostPortPair alternative_destination(alternative_service.host_port_pair()); | 722 HostPortPair alternative_destination(alternative_service.host_port_pair()); |
811 ignore_result( | 723 ignore_result( |
812 ApplyHostMappingRules(request_info_.url, &alternative_destination)); | 724 ApplyHostMappingRules(request_info.url, &alternative_destination)); |
813 | 725 |
814 alternative_job_ = job_factory_->CreateAltSvcJob( | 726 alternative_job_.reset(job_factory_->CreateJob( |
815 this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_, | 727 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, |
816 server_ssl_config_, proxy_ssl_config_, alternative_destination, | 728 proxy_ssl_config, alternative_destination, origin_url, |
817 origin_url, alternative_service, enable_ip_based_pooling_, | 729 alternative_service, enable_ip_based_pooling_, net_log_.net_log())); |
818 net_log_.net_log()); | |
819 | 730 |
820 main_job_is_blocked_ = true; | 731 main_job_is_blocked_ = true; |
821 alternative_job_->Start(request_->stream_type()); | 732 alternative_job_->Start(request_->stream_type()); |
822 } else { | 733 } else { |
823 ProxyServer alternative_proxy_server; | 734 can_start_alternative_proxy_job_ = true; |
824 if (ShouldCreateAlternativeProxyServerJob(proxy_info_, request_info_.url, | |
825 &alternative_proxy_server)) { | |
826 DCHECK(!main_job_is_blocked_); | |
827 ProxyInfo alternative_proxy_info; | |
828 alternative_proxy_info.UseProxyServer(alternative_proxy_server); | |
829 | |
830 alternative_job_ = job_factory_->CreateAltProxyJob( | |
831 this, ALTERNATIVE, session_, request_info_, priority_, | |
832 alternative_proxy_info, server_ssl_config_, proxy_ssl_config_, | |
833 destination, origin_url, alternative_proxy_server, | |
834 enable_ip_based_pooling_, net_log_.net_log()); | |
835 | |
836 can_start_alternative_proxy_job_ = false; | |
837 main_job_is_blocked_ = true; | |
838 alternative_job_->Start(request_->stream_type()); | |
839 } | |
840 } | 735 } |
841 // Even if |alternative_job| has already finished, it will not have notified | 736 // Even if |alternative_job| has already finished, it will not have notified |
842 // the request yet, since we defer that to the next iteration of the | 737 // the request yet, since we defer that to the next iteration of the |
843 // MessageLoop, so starting |main_job_| is always safe. | 738 // MessageLoop, so starting |main_job_| is always safe. |
844 main_job_->Start(request_->stream_type()); | 739 main_job_->Start(request_->stream_type()); |
845 return OK; | |
846 } | 740 } |
847 | 741 |
848 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { | 742 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { |
849 DCHECK(request_); | 743 DCHECK(request_); |
850 DCHECK(job); | 744 DCHECK(job); |
851 DCHECK(job == alternative_job_.get() || job == main_job_.get()); | 745 DCHECK(job == alternative_job_.get() || job == main_job_.get()); |
852 DCHECK(!job_bound_); | 746 DCHECK(!job_bound_); |
853 DCHECK(!bound_job_); | 747 DCHECK(!bound_job_); |
854 | 748 |
855 job_bound_ = true; | 749 job_bound_ = true; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
931 } | 825 } |
932 | 826 |
933 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( | 827 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( |
934 bool was_alpn_negotiated, | 828 bool was_alpn_negotiated, |
935 NextProto negotiated_protocol, | 829 NextProto negotiated_protocol, |
936 bool using_spdy) { | 830 bool using_spdy) { |
937 if (request_) | 831 if (request_) |
938 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy); | 832 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy); |
939 } | 833 } |
940 | 834 |
941 void HttpStreamFactoryImpl::JobController::OnAlternativeServiceJobFailed( | 835 void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed( |
942 int net_error) { | 836 int net_error) { |
943 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); | 837 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); |
944 DCHECK_NE(OK, net_error); | 838 DCHECK_NE(OK, net_error); |
945 DCHECK_NE(kProtoUnknown, alternative_job_->alternative_service().protocol); | |
946 | 839 |
947 alternative_job_net_error_ = net_error; | 840 alternative_job_net_error_ = net_error; |
948 failed_alternative_service_ = alternative_job_->alternative_service(); | 841 |
842 if (alternative_job_->alternative_proxy_server().is_valid()) { | |
843 failed_alternative_proxy_server_ = | |
844 alternative_job_->alternative_proxy_server(); | |
845 } else { | |
846 DCHECK(!failed_alternative_proxy_server_.is_valid()); | |
847 failed_alternative_service_ = alternative_job_->alternative_service(); | |
848 } | |
949 | 849 |
950 if (IsJobOrphaned(alternative_job_.get())) { | 850 if (IsJobOrphaned(alternative_job_.get())) { |
951 // If |request_| is gone then it must have been successfully served by | 851 // If |request_| is gone then it must have been successfully served by |
952 // |main_job_|. | 852 // |main_job_|. |
953 // If |request_| is bound to a different job, then it is being | 853 // If |request_| is bound to a different job, then it is being |
954 // successfully serverd by the main job. | 854 // successfully serverd by the main job. |
955 ReportBrokenAlternativeService(); | 855 ReportBrokenAlternativeService(); |
956 } | 856 } |
957 } | 857 } |
958 | 858 |
959 void HttpStreamFactoryImpl::JobController::OnAlternativeProxyJobFailed( | |
960 int net_error) { | |
961 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); | |
962 DCHECK_NE(OK, net_error); | |
963 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); | |
964 | |
965 // Need to mark alt proxy as broken regardless whether the job is bound. | |
966 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | |
967 if (proxy_delegate) { | |
968 proxy_delegate->OnAlternativeProxyBroken( | |
969 alternative_job_->alternative_proxy_server()); | |
970 } | |
971 } | |
972 | |
973 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { | 859 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { |
974 DCHECK(failed_alternative_service_.protocol != kProtoUnknown); | 860 DCHECK(failed_alternative_service_.protocol != kProtoUnknown || |
861 failed_alternative_proxy_server_.is_valid()); | |
975 DCHECK_NE(OK, alternative_job_net_error_); | 862 DCHECK_NE(OK, alternative_job_net_error_); |
976 | 863 |
977 int error_to_report = alternative_job_net_error_; | 864 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", |
978 alternative_job_net_error_ = OK; | 865 -alternative_job_net_error_); |
979 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", -error_to_report); | |
980 | 866 |
981 if (error_to_report == ERR_NETWORK_CHANGED || | 867 if (alternative_job_net_error_ == ERR_NETWORK_CHANGED || |
982 error_to_report == ERR_INTERNET_DISCONNECTED) { | 868 alternative_job_net_error_ == ERR_INTERNET_DISCONNECTED) { |
983 // No need to mark alternative service or proxy as broken. | 869 // No need to mark alternative service or proxy as broken. |
984 return; | 870 return; |
985 } | 871 } |
986 | 872 |
987 HistogramBrokenAlternateProtocolLocation( | 873 if (failed_alternative_proxy_server_.is_valid()) { |
988 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | 874 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
989 session_->http_server_properties()->MarkAlternativeServiceBroken( | 875 if (proxy_delegate) { |
990 failed_alternative_service_); | 876 proxy_delegate->OnAlternativeProxyBroken( |
877 failed_alternative_proxy_server_); | |
878 } | |
879 } else { | |
880 HistogramBrokenAlternateProtocolLocation( | |
881 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | |
882 session_->http_server_properties()->MarkAlternativeServiceBroken( | |
883 failed_alternative_service_); | |
884 } | |
991 } | 885 } |
992 | 886 |
993 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { | 887 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { |
994 if (!request_ && !main_job_ && !alternative_job_) { | 888 if (!request_ && !main_job_ && !alternative_job_) { |
995 DCHECK(!bound_job_); | 889 DCHECK(!bound_job_); |
996 factory_->OnJobControllerComplete(this); | 890 factory_->OnJobControllerComplete(this); |
997 } | 891 } |
998 } | 892 } |
999 | 893 |
1000 void HttpStreamFactoryImpl::JobController::NotifyRequestFailed(int rv) { | |
1001 if (!request_) | |
1002 return; | |
1003 request_->OnStreamFailed(rv, server_ssl_config_); | |
1004 } | |
1005 | |
1006 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( | 894 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( |
1007 const GURL& url, | 895 const GURL& url, |
1008 HostPortPair* endpoint) { | 896 HostPortPair* endpoint) { |
1009 const HostMappingRules* mapping_rules = session_->params().host_mapping_rules; | 897 const HostMappingRules* mapping_rules = session_->params().host_mapping_rules; |
1010 if (mapping_rules && mapping_rules->RewriteHost(endpoint)) { | 898 if (mapping_rules && mapping_rules->RewriteHost(endpoint)) { |
1011 url::Replacements<char> replacements; | 899 url::Replacements<char> replacements; |
1012 const std::string port_str = base::UintToString(endpoint->port()); | 900 const std::string port_str = base::UintToString(endpoint->port()); |
1013 replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size())); | 901 replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size())); |
1014 replacements.SetHost(endpoint->host().c_str(), | 902 replacements.SetHost(endpoint->host().c_str(), |
1015 url::Component(0, endpoint->host().size())); | 903 url::Component(0, endpoint->host().size())); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1149 | 1037 |
1150 // Ask delegate to mark QUIC as broken for the origin. | 1038 // Ask delegate to mark QUIC as broken for the origin. |
1151 if (quic_advertised && quic_all_broken && delegate != nullptr) | 1039 if (quic_advertised && quic_all_broken && delegate != nullptr) |
1152 delegate->OnQuicBroken(); | 1040 delegate->OnQuicBroken(); |
1153 | 1041 |
1154 return first_alternative_service_info; | 1042 return first_alternative_service_info; |
1155 } | 1043 } |
1156 | 1044 |
1157 bool HttpStreamFactoryImpl::JobController:: | 1045 bool HttpStreamFactoryImpl::JobController:: |
1158 ShouldCreateAlternativeProxyServerJob( | 1046 ShouldCreateAlternativeProxyServerJob( |
1047 Job* job, | |
1159 const ProxyInfo& proxy_info, | 1048 const ProxyInfo& proxy_info, |
1160 const GURL& url, | 1049 const GURL& url, |
1161 ProxyServer* alternative_proxy_server) const { | 1050 ProxyServer* alternative_proxy_server) const { |
1162 DCHECK(!alternative_proxy_server->is_valid()); | 1051 DCHECK(!alternative_proxy_server->is_valid()); |
1163 | 1052 |
1164 if (!enable_alternative_services_) | 1053 if (!enable_alternative_services_) |
1165 return false; | 1054 return false; |
1166 | 1055 |
1167 if (!can_start_alternative_proxy_job_) { | 1056 if (!can_start_alternative_proxy_job_) { |
1168 // Either an alternative service job or an alternative proxy server job has | 1057 // Either an alternative service job or an alternative proxy server job has |
1169 // already been started. | 1058 // already been started. |
1170 return false; | 1059 return false; |
1171 } | 1060 } |
1172 | 1061 |
1062 if (job->job_type() == ALTERNATIVE) { | |
1063 // If |job| is using alternative service, then alternative proxy server | |
1064 // should not be used. | |
1065 return false; | |
1066 } | |
1067 | |
1068 if (is_preconnect_ || job->job_type() == PRECONNECT) { | |
1069 // Preconnects should be fetched using only the main job to keep the | |
1070 // resource utilization down. | |
1071 return false; | |
1072 } | |
1073 | |
1173 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { | 1074 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { |
1174 // Alternative proxy server job can be created only if |job| fetches the | 1075 // Alternative proxy server job can be created only if |job| fetches the |
1175 // |request_| through a non-QUIC proxy. | 1076 // |request_| through a non-QUIC proxy. |
1176 return false; | 1077 return false; |
1177 } | 1078 } |
1178 | 1079 |
1179 if (!url.SchemeIs(url::kHttpScheme)) { | 1080 if (!url.SchemeIs(url::kHttpScheme)) { |
1180 // Only HTTP URLs can be fetched through alternative proxy server, since the | 1081 // Only HTTP URLs can be fetched through alternative proxy server, since the |
1181 // alternative proxy server may not support fetching of URLs with other | 1082 // alternative proxy server may not support fetching of URLs with other |
1182 // schemes. | 1083 // schemes. |
1183 return false; | 1084 return false; |
1184 } | 1085 } |
1185 | 1086 |
1186 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | 1087 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
1187 if (!proxy_delegate) | 1088 if (!proxy_delegate) |
1188 return false; | 1089 return false; |
1090 | |
1189 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), | 1091 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), |
1190 alternative_proxy_server); | 1092 alternative_proxy_server); |
1191 | 1093 |
1192 if (!alternative_proxy_server->is_valid()) | 1094 if (!alternative_proxy_server->is_valid()) |
1193 return false; | 1095 return false; |
1194 | 1096 |
1195 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server())); | 1097 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server())); |
1196 | 1098 |
1197 if (!alternative_proxy_server->is_https() && | 1099 if (!alternative_proxy_server->is_https() && |
1198 !alternative_proxy_server->is_quic()) { | 1100 !alternative_proxy_server->is_quic()) { |
(...skipping 27 matching lines...) Expand all Loading... | |
1226 if (job->using_existing_quic_session()) { | 1128 if (job->using_existing_quic_session()) { |
1227 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, | 1129 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, |
1228 proxy_server_used); | 1130 proxy_server_used); |
1229 return; | 1131 return; |
1230 } | 1132 } |
1231 | 1133 |
1232 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, | 1134 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, |
1233 proxy_server_used); | 1135 proxy_server_used); |
1234 } | 1136 } |
1235 | 1137 |
1138 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() { | |
1139 if (!alternative_job_ || !request_) | |
1140 return; | |
1141 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); | |
1142 alternative_job_->Start(request_->stream_type()); | |
1143 } | |
1144 | |
1236 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { | 1145 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { |
1237 return !request_ || (job_bound_ && bound_job_ != job); | 1146 return !request_ || (job_bound_ && bound_job_ != job); |
1238 } | 1147 } |
1239 | 1148 |
1240 int HttpStreamFactoryImpl::JobController::ReconsiderProxyAfterError(Job* job, | |
1241 int error) { | |
1242 // ReconsiderProxyAfterError() should only be called when the last job fails. | |
1243 DCHECK(!(alternative_job_ && main_job_)); | |
1244 // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is | |
1245 // resolved. | |
1246 CHECK(!pac_request_); | |
1247 DCHECK(session_); | |
1248 | |
1249 if (!job->should_reconsider_proxy()) | |
1250 return error; | |
1251 | |
1252 DCHECK(!job->alternative_proxy_server().is_valid()); | |
1253 | |
1254 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. | |
1255 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) | |
1256 return error; | |
1257 | |
1258 if (request_info_.load_flags & LOAD_BYPASS_PROXY) | |
1259 return error; | |
1260 | |
1261 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { | |
1262 session_->ssl_client_auth_cache()->Remove( | |
1263 proxy_info_.proxy_server().host_port_pair()); | |
1264 } | |
1265 | |
1266 HostPortPair destination(HostPortPair::FromURL(request_info_.url)); | |
1267 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); | |
1268 | |
1269 int rv = session_->proxy_service()->ReconsiderProxyAfterError( | |
1270 origin_url, request_info_.method, error, &proxy_info_, io_callback_, | |
1271 &pac_request_, session_->params().proxy_delegate, net_log_); | |
1272 if (rv == OK || rv == ERR_IO_PENDING) { | |
1273 RemoveRequestFromSpdySessionRequestMap(); | |
1274 // Abandon all Jobs and start over. | |
1275 job_bound_ = false; | |
1276 bound_job_ = nullptr; | |
1277 alternative_job_.reset(); | |
1278 main_job_.reset(); | |
1279 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | |
1280 } else { | |
1281 // If ReconsiderProxyAfterError() failed synchronously, it means | |
1282 // there was nothing left to fall-back to, so fail the transaction | |
1283 // with the last connection error we got. | |
1284 // TODO(eroman): This is a confusing contract, make it more obvious. | |
1285 rv = error; | |
1286 } | |
1287 return rv; | |
1288 } | |
1289 | |
1290 } // namespace net | 1149 } // namespace net |
OLD | NEW |