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

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

Issue 2895263003: Revert CLs landed in HttpStreamFactoryImpl to track down a crasher (Closed)
Patch Set: Revert "Fix SpdySessionKey for HTTP/2 alternative Jobs." 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 <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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/http/http_stream_factory_impl_job_controller.h ('k') | net/http/http_stream_factory_impl_job_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698