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 "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 HttpStreamFactoryImpl* factory, | 31 HttpStreamFactoryImpl* factory, |
32 HttpStreamRequest::Delegate* delegate, | 32 HttpStreamRequest::Delegate* delegate, |
33 HttpNetworkSession* session, | 33 HttpNetworkSession* session, |
34 JobFactory* job_factory) | 34 JobFactory* job_factory) |
35 : factory_(factory), | 35 : factory_(factory), |
36 session_(session), | 36 session_(session), |
37 job_factory_(job_factory), | 37 job_factory_(job_factory), |
38 request_(nullptr), | 38 request_(nullptr), |
39 delegate_(delegate), | 39 delegate_(delegate), |
40 is_preconnect_(false), | 40 is_preconnect_(false), |
41 alternative_job_is_failed_(false), | |
41 job_bound_(false), | 42 job_bound_(false), |
42 main_job_is_blocked_(false), | 43 main_job_is_blocked_(false), |
43 bound_job_(nullptr), | 44 bound_job_(nullptr), |
44 can_start_alternative_proxy_job_(false), | 45 can_start_alternative_proxy_job_(false), |
45 ptr_factory_(this) { | 46 ptr_factory_(this) { |
46 DCHECK(factory); | 47 DCHECK(factory); |
47 } | 48 } |
48 | 49 |
49 HttpStreamFactoryImpl::JobController::~JobController() { | 50 HttpStreamFactoryImpl::JobController::~JobController() { |
50 main_job_.reset(); | 51 main_job_.reset(); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 request_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info, | 213 request_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info, |
213 stream.release()); | 214 stream.release()); |
214 } | 215 } |
215 | 216 |
216 void HttpStreamFactoryImpl::JobController::OnWebSocketHandshakeStreamReady( | 217 void HttpStreamFactoryImpl::JobController::OnWebSocketHandshakeStreamReady( |
217 Job* job, | 218 Job* job, |
218 const SSLConfig& used_ssl_config, | 219 const SSLConfig& used_ssl_config, |
219 const ProxyInfo& used_proxy_info, | 220 const ProxyInfo& used_proxy_info, |
220 WebSocketHandshakeStreamBase* stream) { | 221 WebSocketHandshakeStreamBase* stream) { |
221 DCHECK(job); | 222 DCHECK(job); |
222 | |
223 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), | 223 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), |
224 job->using_spdy()); | 224 job->using_spdy()); |
225 | 225 |
226 if (!request_) | 226 if (!request_) |
227 return; | 227 return; |
228 DCHECK(factory_->for_websockets_); | 228 DCHECK(factory_->for_websockets_); |
229 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); | 229 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); |
230 DCHECK(stream); | 230 DCHECK(stream); |
231 | 231 |
232 OnJobSucceeded(job); | 232 OnJobSucceeded(job); |
233 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, | 233 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, |
234 stream); | 234 stream); |
235 } | 235 } |
236 | 236 |
237 void HttpStreamFactoryImpl::JobController::OnStreamFailed( | 237 void HttpStreamFactoryImpl::JobController::OnStreamFailed( |
238 Job* job, | 238 Job* job, |
239 int status, | 239 int status, |
240 const SSLConfig& used_ssl_config) { | 240 const SSLConfig& used_ssl_config) { |
241 if (job->job_type() == ALTERNATIVE) | |
242 OnAlternativeJobFailed(job); | |
243 | |
241 MaybeResumeMainJob(job, base::TimeDelta()); | 244 MaybeResumeMainJob(job, base::TimeDelta()); |
242 | 245 |
243 if (job_bound_ && bound_job_ != job) { | 246 if (job_bound_ && bound_job_ != job) { |
244 // We have bound a job to the associated Request, |job| has been orphaned. | 247 // We have bound a job to the associated Request, |job| has been orphaned. |
245 OnOrphanedJobComplete(job); | 248 OnOrphanedJobComplete(job); |
246 return; | 249 return; |
247 } | 250 } |
248 | 251 |
249 if (!request_) | 252 if (!request_) |
250 return; | 253 return; |
251 DCHECK_NE(OK, status); | 254 DCHECK_NE(OK, status); |
252 DCHECK(job); | 255 DCHECK(job); |
253 | 256 |
254 if (!bound_job_) { | 257 if (!bound_job_) { |
255 if (main_job_ && alternative_job_) { | 258 if (main_job_ && alternative_job_) { |
256 // Hey, we've got other jobs! Maybe one of them will succeed, let's just | 259 // Hey, we've got other jobs! Maybe one of them will succeed, let's just |
257 // ignore this failure. | 260 // ignore this failure. |
258 factory_->request_map_.erase(job); | 261 factory_->request_map_.erase(job); |
259 // Notify all the other jobs that this one failed. | |
260 if (job->job_type() == MAIN) { | 262 if (job->job_type() == MAIN) { |
261 alternative_job_->MarkOtherJobComplete(*job); | |
262 main_job_.reset(); | 263 main_job_.reset(); |
263 } else { | 264 } else { |
264 DCHECK(job->job_type() == ALTERNATIVE); | 265 DCHECK(job->job_type() == ALTERNATIVE); |
265 main_job_->MarkOtherJobComplete(*job); | |
266 alternative_job_.reset(); | 266 alternative_job_.reset(); |
267 } | 267 } |
268 return; | 268 return; |
269 } else { | 269 } else { |
270 BindJob(job); | 270 BindJob(job); |
271 } | 271 } |
272 } | 272 } |
273 | 273 |
274 request_->OnStreamFailed(status, used_ssl_config); | 274 request_->OnStreamFailed(status, used_ssl_config); |
275 } | 275 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
413 const bool was_npn_negotiated = job->was_npn_negotiated(); | 413 const bool was_npn_negotiated = job->was_npn_negotiated(); |
414 const NextProto negotiated_protocol = job->negotiated_protocol(); | 414 const NextProto negotiated_protocol = job->negotiated_protocol(); |
415 const bool using_spdy = job->using_spdy(); | 415 const bool using_spdy = job->using_spdy(); |
416 const BoundNetLog net_log = job->net_log(); | 416 const BoundNetLog net_log = job->net_log(); |
417 | 417 |
418 // Cache this so we can still use it if the JobController is deleted. | 418 // Cache this so we can still use it if the JobController is deleted. |
419 HttpStreamFactoryImpl* factory = factory_; | 419 HttpStreamFactoryImpl* factory = factory_; |
420 | 420 |
421 // Notify |request_|. | 421 // Notify |request_|. |
422 if (!is_preconnect_ && !is_job_orphaned) { | 422 if (!is_preconnect_ && !is_job_orphaned) { |
423 if (job->job_type() == MAIN && alternative_job_is_failed_) | |
424 ReportBrokenAlternativeService(); | |
425 | |
423 DCHECK(request_); | 426 DCHECK(request_); |
424 | 427 |
425 // The first case is the usual case. | 428 // The first case is the usual case. |
426 if (!job_bound_) { | 429 if (!job_bound_) { |
427 BindJob(job); | 430 BindJob(job); |
428 } | 431 } |
429 | 432 |
430 MarkRequestComplete(was_npn_negotiated, negotiated_protocol, using_spdy); | 433 MarkRequestComplete(was_npn_negotiated, negotiated_protocol, using_spdy); |
431 | 434 |
432 std::unique_ptr<HttpStream> stream; | 435 std::unique_ptr<HttpStream> stream; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
497 base::Bind(&NetLogHttpStreamJobDelayCallback, main_job_wait_time_)); | 500 base::Bind(&NetLogHttpStreamJobDelayCallback, main_job_wait_time_)); |
498 | 501 |
499 main_job_->Resume(); | 502 main_job_->Resume(); |
500 main_job_wait_time_ = base::TimeDelta(); | 503 main_job_wait_time_ = base::TimeDelta(); |
501 } | 504 } |
502 | 505 |
503 void HttpStreamFactoryImpl::JobController::MaybeResumeMainJob( | 506 void HttpStreamFactoryImpl::JobController::MaybeResumeMainJob( |
504 Job* job, | 507 Job* job, |
505 const base::TimeDelta& delay) { | 508 const base::TimeDelta& delay) { |
506 DCHECK(job == main_job_.get() || job == alternative_job_.get()); | 509 DCHECK(job == main_job_.get() || job == alternative_job_.get()); |
510 | |
507 if (!main_job_is_blocked_ || job != alternative_job_.get() || !main_job_) | 511 if (!main_job_is_blocked_ || job != alternative_job_.get() || !main_job_) |
508 return; | 512 return; |
509 | 513 |
510 main_job_is_blocked_ = false; | 514 main_job_is_blocked_ = false; |
511 | 515 |
512 if (!main_job_->is_waiting()) | 516 if (!main_job_->is_waiting()) |
513 return; | 517 return; |
514 | 518 |
515 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 519 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
516 FROM_HERE, | 520 FROM_HERE, |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 // because we *WANT* to cancel the unnecessary Jobs from other requests if | 728 // because we *WANT* to cancel the unnecessary Jobs from other requests if |
725 // another Job completes first. | 729 // another Job completes first. |
726 // TODO(mbelshe): Revisit this when we implement ip connection pooling of | 730 // TODO(mbelshe): Revisit this when we implement ip connection pooling of |
727 // SpdySessions. Do we want to orphan the jobs for a different hostname so | 731 // SpdySessions. Do we want to orphan the jobs for a different hostname so |
728 // they complete? Or do we want to prevent connecting a new SpdySession if | 732 // they complete? Or do we want to prevent connecting a new SpdySession if |
729 // we've already got one available for a different hostname where the ip | 733 // we've already got one available for a different hostname where the ip |
730 // address matches up? | 734 // address matches up? |
731 CancelJobs(); | 735 CancelJobs(); |
732 return; | 736 return; |
733 } | 737 } |
738 | |
739 if (job->job_type() == MAIN && alternative_job_is_failed_) | |
740 ReportBrokenAlternativeService(); | |
741 | |
734 if (!bound_job_) { | 742 if (!bound_job_) { |
735 if (main_job_ && alternative_job_) { | 743 if (main_job_ && alternative_job_) |
736 job->ReportJobSucceededForRequest(); | 744 job->ReportJobSucceededForRequest(); |
737 // Notify all the other jobs that this one succeeded. | |
738 if (job->job_type() == MAIN) { | |
739 alternative_job_->MarkOtherJobComplete(*job); | |
740 } else { | |
741 DCHECK(job->job_type() == ALTERNATIVE); | |
742 main_job_->MarkOtherJobComplete(*job); | |
743 } | |
744 } | |
745 BindJob(job); | 745 BindJob(job); |
746 return; | 746 return; |
747 } | 747 } |
748 DCHECK(bound_job_); | 748 DCHECK(bound_job_); |
749 } | 749 } |
750 | 750 |
751 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( | 751 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( |
752 bool was_npn_negotiated, | 752 bool was_npn_negotiated, |
753 NextProto negotiated_protocol, | 753 NextProto negotiated_protocol, |
754 bool using_spdy) { | 754 bool using_spdy) { |
755 if (request_) | 755 if (request_) |
756 request_->Complete(was_npn_negotiated, negotiated_protocol, using_spdy); | 756 request_->Complete(was_npn_negotiated, negotiated_protocol, using_spdy); |
757 } | 757 } |
758 | 758 |
759 void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed(Job* job) { | |
760 DCHECK_EQ(job->job_type(), ALTERNATIVE); | |
761 | |
762 alternative_job_is_failed_ = true; | |
763 | |
764 if (job->alternative_proxy_server().is_valid()) { | |
765 broken_alternative_proxy_server_ = job->alternative_proxy_server(); | |
766 } else { | |
767 DCHECK(!broken_alternative_proxy_server_.is_valid()); | |
768 broken_alternative_service_ = job->alternative_service(); | |
769 } | |
770 | |
771 if (!request_ || (job_bound_ && bound_job_ != job)) { | |
772 // If |request_| is gone and |job| is still running, it must be successfully | |
773 // served by |main_job_|. Or if |request_| already has a different Job | |
774 // bound, | |
775 // |main_job_| must succeed. | |
Ryan Hamilton
2016/09/14 23:13:04
// If |request_| is gone then it must have been su
| |
776 ReportBrokenAlternativeService(); | |
777 } | |
778 } | |
779 | |
780 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { | |
781 DCHECK(broken_alternative_service_.protocol != | |
782 UNINITIALIZED_ALTERNATE_PROTOCOL || | |
783 broken_alternative_proxy_server_.is_valid()); | |
784 | |
785 if (broken_alternative_proxy_server_.is_valid()) { | |
786 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | |
787 if (proxy_delegate) | |
788 proxy_delegate->OnAlternativeProxyBroken( | |
789 broken_alternative_proxy_server_); | |
790 } else { | |
791 HistogramBrokenAlternateProtocolLocation( | |
792 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | |
793 session_->http_server_properties()->MarkAlternativeServiceBroken( | |
794 broken_alternative_service_); | |
795 } | |
796 session_->quic_stream_factory()->OnTcpJobCompleted(true); | |
797 } | |
798 | |
759 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { | 799 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { |
760 if (!request_ && !main_job_ && !alternative_job_) { | 800 if (!request_ && !main_job_ && !alternative_job_) { |
761 DCHECK(!bound_job_); | 801 DCHECK(!bound_job_); |
762 factory_->OnJobControllerComplete(this); | 802 factory_->OnJobControllerComplete(this); |
763 } | 803 } |
764 } | 804 } |
765 | 805 |
766 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( | 806 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( |
767 const GURL& url, | 807 const GURL& url, |
768 HostPortPair* endpoint) { | 808 HostPortPair* endpoint) { |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1000 // Check that QUIC is enabled globally, and it is not disabled. | 1040 // Check that QUIC is enabled globally, and it is not disabled. |
1001 if (!session_->params().enable_quic || | 1041 if (!session_->params().enable_quic || |
1002 session_->quic_stream_factory()->IsQuicDisabled()) { | 1042 session_->quic_stream_factory()->IsQuicDisabled()) { |
1003 return false; | 1043 return false; |
1004 } | 1044 } |
1005 } | 1045 } |
1006 | 1046 |
1007 return true; | 1047 return true; |
1008 } | 1048 } |
1009 } | 1049 } |
OLD | NEW |